001         package com.croftsoft.core.animation.awt;
002    
003    // Need to make sure slip and disappear work when the backgroundImage
004    // is null without leaving a snail trail.
005    
006    // See other comment below about when window minimized.
007    
008         import com.croftsoft.core.awt.GraphicsLib;  // for rasterize()
009    
010         import java.awt.*;
011         import java.util.*;
012    
013         /*********************************************************************
014         * If you use a backgroundImage, you must dispose of its graphics
015         * yourself.
016         * <P>
017         * @version
018         *   1997-04-28
019         * @author
020         *   <A HREF="http://www.alumni.caltech.edu/~croft">David W. Croft</A>
021         *********************************************************************/
022    
023         public class  SpriteCanvas extends Canvas {
024         //////////////////////////////////////////////////////////////////////
025         //////////////////////////////////////////////////////////////////////
026    
027         protected Dimension  size;
028    
029         private Color      background_Color;
030    
031         private Hashtable  sprite_Hashtable = new Hashtable ( );
032    
033         private Graphics   graphics;
034         private Image      offscreenImage;
035         private Graphics   offscreenGraphics;
036         private Image      backgroundImage;
037    
038         private boolean    graphics_initialized;
039    
040         //////////////////////////////////////////////////////////////////////
041         //////////////////////////////////////////////////////////////////////
042    
043         public  SpriteCanvas ( Color  background_Color ) {
044         //////////////////////////////////////////////////////////////////////
045           this.background_Color = background_Color;
046           setBackground ( background_Color );
047         }
048    
049         public void  setBackgroundImage ( Image  backgroundImage ) {
050         //////////////////////////////////////////////////////////////////////
051           this.backgroundImage = backgroundImage;
052           redraw_all ( );
053         }
054    
055         public void  paint ( Graphics  g ) {
056         //////////////////////////////////////////////////////////////////////
057           if ( !graphics_initialized ) init_graphics ( );
058           graphics.drawImage ( offscreenImage, 0, 0, this );
059         }
060    
061         public synchronized void  init_graphics ( ) {
062         //////////////////////////////////////////////////////////////////////
063           try {
064             graphics_initialized = false;
065             clear_graphics ( );
066             graphics = getGraphics ( );
067             if ( graphics == null ) return;
068             size = size ( );
069             offscreenImage = createImage ( size.width, size.height );
070             if ( offscreenImage == null ) return;
071             offscreenGraphics = offscreenImage.getGraphics ( );
072             redraw_all ( );
073             graphics_initialized = true;
074           } catch ( Exception  e ) { e.printStackTrace ( ); }
075         }
076    
077         public synchronized void  reshape (
078           int  x, int  y, int  width, int  height ) {
079         //////////////////////////////////////////////////////////////////////
080           try {
081             super.reshape ( x, y, width, height );
082             if ( !size ( ).equals ( this.size ) ) init_graphics ( );
083           } catch ( Exception  e ) { e.printStackTrace ( ); }
084         }
085    
086         private synchronized void  clear_graphics ( ) {
087         //////////////////////////////////////////////////////////////////////
088           try {
089             if ( offscreenGraphics != null ) {
090               offscreenGraphics.dispose ( );
091               offscreenGraphics = null;
092             }
093             offscreenImage = null;
094           } catch ( Exception  e ) { e.printStackTrace ( ); }
095         }
096    
097         public synchronized void  redraw_all ( ) {
098         //////////////////////////////////////////////////////////////////////
099           try {
100             if ( offscreenGraphics == null ) return;
101             offscreenGraphics.setColor ( background_Color );
102             offscreenGraphics.fillRect ( 0, 0, size.width, size.height );
103             if ( backgroundImage != null ) {
104               offscreenGraphics.drawImage ( backgroundImage, 0, 0, this );
105             }
106             Enumeration  e = sprite_Hashtable.elements ( );
107             while ( e.hasMoreElements ( ) ) {
108               Sprite  sprite = ( Sprite ) e.nextElement ( );
109               offscreenGraphics.drawImage (
110                 sprite.image, sprite.x, sprite.y, this );
111             }
112             graphics.drawImage ( offscreenImage, 0, 0, this );
113           } catch ( Exception  e ) { e.printStackTrace ( ); }
114         }
115    
116         public void  repaint ( ) {
117         //////////////////////////////////////////////////////////////////////
118           paint ( null );
119         }
120    
121         public void  update ( Graphics  g ) {
122         //////////////////////////////////////////////////////////////////////
123           paint ( null );
124         }
125    
126         private void  double_drawImage (
127           Image  image,
128           int    x,
129           int    y ) {
130         //////////////////////////////////////////////////////////////////////
131           try {
132             if ( graphics == null ) init_graphics ( );
133    // Is this extra check a problem for speed?
134             if ( graphics == null ) return;
135             graphics.drawImage ( image, x, y, this );
136    // For some reason, when the window is minimized, the offscreenGraphics
137    // is null!!!!!!!!!!!!!!!??????/
138             if ( offscreenGraphics != null ) {
139               offscreenGraphics.drawImage ( image, x, y, this );
140             }
141           } catch ( Exception  e ) { e.printStackTrace ( ); }
142         }
143    
144         //////////////////////////////////////////////////////////////////////
145         //////////////////////////////////////////////////////////////////////
146    
147         public synchronized void  add ( Sprite  sprite ) {
148         //////////////////////////////////////////////////////////////////////
149           sprite_Hashtable.put ( new Long ( sprite.id ), sprite );
150           sprite.scratchImage = createImage ( sprite.w + 1, sprite.h + 1 );
151           sprite.scratchGraphics = sprite.scratchImage.getGraphics ( );
152           sprite.scratchGraphics.setColor ( background_Color );
153           double_drawImage ( sprite.image, sprite.x, sprite.y );
154         }
155    
156         public synchronized void  remove ( Sprite  sprite ) {
157         //////////////////////////////////////////////////////////////////////
158           sprite_Hashtable.remove ( new Long ( sprite.id ) );
159           disappear ( sprite );
160           sprite.scratchGraphics.dispose ( );
161           sprite.scratchGraphics = null;
162           sprite.scratchImage = null;
163         }
164    
165         public Sprite  get_sprite ( long  sprite_id ) {
166         //////////////////////////////////////////////////////////////////////
167           return ( Sprite ) sprite_Hashtable.get ( new Long ( sprite_id ) );
168         }
169    
170         public void  setImage ( long  sprite_id, Image  image ) {
171         //////////////////////////////////////////////////////////////////////
172           Sprite  sprite
173             = ( Sprite ) sprite_Hashtable.get ( new Long ( sprite_id ) );
174           sprite.setImage ( image );
175         }
176    
177         public synchronized void  slide (
178           long  sprite_id, int  dest_x, int  dest_y ) {
179         //////////////////////////////////////////////////////////////////////
180           try {
181             Sprite  sprite
182               = ( Sprite ) sprite_Hashtable.get ( new Long ( sprite_id ) );
183             slide ( sprite, dest_x, dest_y );
184           } catch ( Exception  e ) { e.printStackTrace ( ); }
185         }
186    
187         public synchronized void  slide (
188           Sprite  sprite, int  dest_x, int  dest_y ) {
189         //////////////////////////////////////////////////////////////////////
190           try {
191           if ( ( sprite.x == dest_x ) && ( sprite.y == dest_y ) ) return;
192           Point [ ]  points = GraphicsLib.rasterize (
193             new Point ( sprite.x, sprite.y ), new Point ( dest_x, dest_y ) );
194           for ( int  i = 0; i < points.length; i++ ) {
195             slip ( sprite,
196               points [ i ].x - sprite.x, points [ i ].y - sprite.y );
197           }
198           } catch ( Exception  e ) { e.printStackTrace ( ); }
199         }
200    
201         /*********************************************************************
202         * Slips the sprite one pixel along the axes.<BR>
203         * Distances dist_x and dist_y should be -1, 0, or +1.
204         *********************************************************************/
205         public synchronized void  slip (
206           Sprite  sprite, int  dist_x, int  dist_y ) {
207         //////////////////////////////////////////////////////////////////////
208           try {
209           synchronized ( sprite ) {
210             int  pos_x = 0, pos_y = 0;
211             int  corner_x = sprite.x;
212             int  corner_y = sprite.y;
213             if ( dist_x > 0 ) {
214               pos_x = 1;
215             } else if ( dist_x < 0 ) {
216               corner_x -= 1;
217             }
218             if ( dist_y > 0 ) {
219               pos_y = 1;
220             } else if ( dist_y < 0 ) {
221               corner_y -= 1;
222             }
223             sprite.scratchGraphics.fillRect (
224               0, 0, sprite.w + 1, sprite.h + 1 );
225             if ( backgroundImage != null ) {
226               sprite.scratchGraphics.drawImage (
227                 backgroundImage, -corner_x, -corner_y, this );
228             }
229             sprite.scratchGraphics.drawImage (
230               sprite.image, pos_x, pos_y, this );
231             sprite.x += ( dist_x > 0 ? 1 : ( dist_x < 0 ? -1 : 0 ) );
232             sprite.y += ( dist_y > 0 ? 1 : ( dist_y < 0 ? -1 : 0 ) );
233             double_drawImage ( sprite.scratchImage, corner_x, corner_y );
234           }
235           } catch ( Exception  e ) { e.printStackTrace ( ); }
236         }
237    
238         public void  disappear ( Sprite  sprite ) {
239         //////////////////////////////////////////////////////////////////////
240           try {
241             synchronized ( sprite ) {
242               sprite.scratchGraphics.fillRect (
243                 0, 0, sprite.w + 1, sprite.h + 1 );
244               if ( backgroundImage != null ) {
245                 sprite.scratchGraphics.drawImage (
246                   backgroundImage, -sprite.x, -sprite.y, this );
247               }
248               double_drawImage ( sprite.scratchImage, sprite.x, sprite.y );
249             }
250           } catch ( Exception  e ) { e.printStackTrace ( ); }
251         }
252    
253         public void  finalize ( ) throws Throwable {
254         //////////////////////////////////////////////////////////////////////
255           clear_graphics ( );
256           super.finalize ( );
257         }
258    
259         //////////////////////////////////////////////////////////////////////
260         //////////////////////////////////////////////////////////////////////
261         }