001         package com.croftsoft.apps.dodger;
002    
003         import java.applet.*;
004         import java.awt.*;
005         import java.awt.event.*;
006         import java.awt.geom.*;
007         import java.util.Random;
008         import javax.swing.*;
009         import javax.swing.event.*;
010    
011         import com.croftsoft.core.lang.NullArgumentException;
012         import com.croftsoft.core.animation.*;
013         import com.croftsoft.core.animation.sprite.*;
014    
015         /*********************************************************************
016         * An IconSprite subclass representing a Dodger obstacle.
017         *
018         * @version
019         *   2002-03-23
020         * @since
021         *   2002-03-18
022         * @author
023         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
024         *********************************************************************/
025    
026         public class  ObstacleSprite
027           extends AbstractSprite
028         //////////////////////////////////////////////////////////////////////
029         //////////////////////////////////////////////////////////////////////
030         {
031    
032         private static final int   OBSTACLE_WIDTH        = 32;
033    
034         private static final int   OBSTACLE_HEIGHT       = 32;
035    
036         private static final long  EXPLODE_PERIOD_MILLIS = 1000;
037    
038         //
039    
040         private final AudioClip  explodeAudioClip;
041    
042         private final Random     random;
043    
044         private final Rectangle  bounds;
045    
046         private final int        pixelsPerFrame;
047    
048         private final Rectangle  paintBounds;
049    
050         //
051    
052         private Color    color;
053    
054         private long     explodeTimeMillis;
055    
056         private boolean  hit;
057    
058         private boolean  exploding;
059    
060         //////////////////////////////////////////////////////////////////////
061         // constructor methods
062         //////////////////////////////////////////////////////////////////////
063    
064    
065         public  ObstacleSprite (
066           AudioClip  explodeAudioClip,
067           Random     random,
068           Rectangle  bounds,
069           int        pixelsPerFrame )
070         //////////////////////////////////////////////////////////////////////
071         {
072           NullArgumentException.check (
073             this.explodeAudioClip = explodeAudioClip );
074    
075           NullArgumentException.check ( this.random = random );
076    
077           NullArgumentException.check ( this.bounds = bounds );
078    
079           this.pixelsPerFrame = pixelsPerFrame;
080    
081           paintBounds = new Rectangle (
082             0, 0, OBSTACLE_WIDTH, OBSTACLE_HEIGHT );       
083    
084           setY ( Double.POSITIVE_INFINITY );
085    
086           color = new Color (
087             random.nextInt ( 256 ),
088             random.nextInt ( 256 ),
089             random.nextInt ( 256 ) );
090         }
091    
092         //////////////////////////////////////////////////////////////////////
093         // accessor methods
094         //////////////////////////////////////////////////////////////////////
095    
096         public void  getPaintBounds ( Rectangle  paintBounds )
097         //////////////////////////////////////////////////////////////////////
098         {
099           paintBounds.setBounds ( this.paintBounds );
100         }
101    
102         public Shape  getCollisionShape ( )
103         //////////////////////////////////////////////////////////////////////
104         {
105           if ( exploding )
106           {
107             return null;
108           }
109    
110           return paintBounds;
111         }
112    
113         //////////////////////////////////////////////////////////////////////
114         // mutator methods
115         //////////////////////////////////////////////////////////////////////
116    
117         public void  setX ( double  x )
118         //////////////////////////////////////////////////////////////////////
119         {
120           super.setX ( x );
121    
122           paintBounds.x = ( int ) Math.round ( x );
123         }
124    
125         public void  setY ( double  y )
126         //////////////////////////////////////////////////////////////////////
127         {
128           super.setY ( y );
129    
130           paintBounds.y = ( int ) Math.round ( y );
131         }
132    
133         public void  setHit ( )
134         //////////////////////////////////////////////////////////////////////
135         {
136           hit = true;
137         }
138    
139         public void  reset ( )
140         //////////////////////////////////////////////////////////////////////
141         {
142           hit = false;
143    
144           exploding = false;
145    
146           setX ( -OBSTACLE_WIDTH
147             + random.nextInt ( bounds.width + OBSTACLE_WIDTH ) );
148    
149           setY ( -random.nextInt ( bounds.height ) - OBSTACLE_HEIGHT );
150    
151           color = new Color (
152             random.nextInt ( 256 ),
153             random.nextInt ( 256 ),
154             random.nextInt ( 256 ) );
155         }
156    
157         //////////////////////////////////////////////////////////////////////
158         // interface ComponentAnimator methods
159         //////////////////////////////////////////////////////////////////////
160    
161         public void  update ( JComponent  component )
162         //////////////////////////////////////////////////////////////////////
163         {
164           long  updateTimeMillis = System.currentTimeMillis ( );
165    
166           double  y = getY ( );
167    
168           y += pixelsPerFrame;
169    
170           if ( y >= bounds.height )
171           {
172             reset ( );
173           }
174           else
175           {
176             setY ( y );
177           }
178    
179           if ( exploding )
180           {
181             if ( updateTimeMillis
182               >= explodeTimeMillis + EXPLODE_PERIOD_MILLIS )
183             {
184               reset ( );
185             }
186    
187             color = new Color (
188               random.nextInt ( 256 ),
189               random.nextInt ( 256 ),
190               random.nextInt ( 256 ) );
191           }
192           else if ( hit )
193           {
194             explodeAudioClip.play ( );
195    
196             color = new Color (
197               random.nextInt ( 256 ),
198               random.nextInt ( 256 ),
199               random.nextInt ( 256 ) );
200    
201             explodeTimeMillis = updateTimeMillis;
202             
203             exploding = true;
204           }
205         }
206    
207         public void  paint (
208           JComponent  component,
209           Graphics2D  graphics )
210         //////////////////////////////////////////////////////////////////////
211         {
212           graphics.setColor ( color );
213    
214           graphics.fillRect (
215             paintBounds.x,
216             paintBounds.y,
217             OBSTACLE_WIDTH,
218             OBSTACLE_HEIGHT );
219    
220           graphics.setColor ( Color.BLACK );
221    
222           graphics.drawRect (
223             paintBounds.x,
224             paintBounds.y,
225             OBSTACLE_WIDTH,
226             OBSTACLE_HEIGHT );
227         }
228    
229         //////////////////////////////////////////////////////////////////////
230         //////////////////////////////////////////////////////////////////////
231         }