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 }