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 }