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.beans.*;
008 import java.util.Random;
009 import javax.swing.*;
010 import javax.swing.event.*;
011
012 import com.croftsoft.core.lang.NullArgumentException;
013 import com.croftsoft.core.animation.*;
014 import com.croftsoft.core.animation.sprite.IconSprite;
015
016 /*********************************************************************
017 * An IconSprite subclass representing the Dodger.
018 *
019 * @version
020 * 2003-07-12
021 * @since
022 * 2002-03-18
023 * @author
024 * <a href="https://www.croftsoft.com/">David Wallace Croft</a>
025 *********************************************************************/
026
027 public class DodgerSprite
028 extends IconSprite
029 implements KeyListener, MouseInputListener
030 //////////////////////////////////////////////////////////////////////
031 //////////////////////////////////////////////////////////////////////
032 {
033
034 private static final long IDLE_TIMEOUT_MILLIS = 60 * 1000;
035
036 private static final long INIT_RECHARGE_PERIOD_MILLIS = 1;
037
038 private static final long BANG_PERIOD_MILLIS = 300;
039
040 private static final long RECOVERY_PERIOD_MILLIS = 1000;
041
042 //
043
044 private static final int STATE_GREEN = 0;
045
046 private static final int STATE_YELLOW = 1;
047
048 private static final int STATE_RED = 2;
049
050 private static final int STATE_BANG = 3;
051
052 private static final int STATE_BOOM = 4;
053
054 //
055
056 private final Icon greenIcon;
057
058 private final Icon yellowIcon;
059
060 private final Icon redIcon;
061
062 private final Icon bangIcon;
063
064 private final Icon boomIcon;
065
066 private final AudioClip bangAudioClip;
067
068 private final Rectangle bounds;
069
070 private final int dodgerWidth;
071
072 private final int dodgerHalfWidth;
073
074 private final int dodgerHalfHeight;
075
076 private final int dodgerVerticalOffset;
077
078 private final Rectangle2D shootArea;
079
080 private final Rectangle paintBounds;
081
082 //
083
084 private long rechargePeriodMillis;
085
086 private boolean bang;
087
088 private long bangTimeMillis;
089
090 private Point mousePoint;
091
092 private boolean shooting;
093
094 private long score;
095
096 private long lastMoveTimeMillis;
097
098 private int state;
099
100 private long boomTimeMillis;
101
102 //////////////////////////////////////////////////////////////////////
103 // constructor methods
104 //////////////////////////////////////////////////////////////////////
105
106
107 public DodgerSprite (
108 Icon greenIcon,
109 Icon yellowIcon,
110 Icon redIcon,
111 Icon bangIcon,
112 Icon boomIcon,
113 AudioClip bangAudioClip,
114 Rectangle bounds )
115 //////////////////////////////////////////////////////////////////////
116 {
117 super ( 0.0, 0.0, 0.0, 0.0, 0.0, null, greenIcon );
118
119 NullArgumentException.check ( this.greenIcon = greenIcon );
120
121 NullArgumentException.check ( this.yellowIcon = yellowIcon );
122
123 NullArgumentException.check ( this.redIcon = redIcon );
124
125 NullArgumentException.check ( this.bangIcon = bangIcon );
126
127 NullArgumentException.check ( this.boomIcon = boomIcon );
128
129 NullArgumentException.check ( this.bangAudioClip = bangAudioClip );
130
131 NullArgumentException.check ( this.bounds = bounds );
132
133 dodgerWidth = greenIcon.getIconWidth ( );
134
135 dodgerHalfWidth = dodgerWidth / 2;
136
137 dodgerHalfHeight = greenIcon.getIconHeight ( ) / 2;
138
139 dodgerVerticalOffset = 3 * dodgerHalfHeight;
140
141 shootArea = new Rectangle2D.Double ( );
142
143 paintBounds = new Rectangle ( );
144
145 setX ( Double.POSITIVE_INFINITY );
146
147 rechargePeriodMillis = INIT_RECHARGE_PERIOD_MILLIS;
148 }
149
150 //////////////////////////////////////////////////////////////////////
151 // accessor methods
152 //////////////////////////////////////////////////////////////////////
153
154 public long getScore ( ) { return score; }
155
156 public boolean isShooting ( ) { return shooting; }
157
158 public Rectangle2D getShootArea ( ) { return shootArea; }
159
160 //////////////////////////////////////////////////////////////////////
161 // mutator methods
162 //////////////////////////////////////////////////////////////////////
163
164 public void resetScore ( )
165 //////////////////////////////////////////////////////////////////////
166 {
167 score = 0;
168 }
169
170 public void setHit ( )
171 //////////////////////////////////////////////////////////////////////
172 {
173 rechargePeriodMillis = INIT_RECHARGE_PERIOD_MILLIS;
174
175 score = 0;
176
177 setIcon ( boomIcon );
178
179 state = STATE_BOOM;
180
181 boomTimeMillis = System.currentTimeMillis ( );
182 }
183
184 //////////////////////////////////////////////////////////////////////
185 // interface ComponentAnimator methods
186 //////////////////////////////////////////////////////////////////////
187
188 public void update ( JComponent component )
189 //////////////////////////////////////////////////////////////////////
190 {
191 long updateTimeMillis = System.currentTimeMillis ( );
192
193 if ( updateTimeMillis >= lastMoveTimeMillis + IDLE_TIMEOUT_MILLIS )
194 {
195 setX ( Integer.MAX_VALUE );
196
197 return;
198 }
199
200 score++;
201
202 shooting = false;
203
204 if ( bang
205 && ( updateTimeMillis >= bangTimeMillis + rechargePeriodMillis ) )
206 {
207 shooting = true;
208
209 rechargePeriodMillis = 2 * rechargePeriodMillis;
210
211 shootArea.setRect ( getX ( ), 0, dodgerWidth, getY ( ) );
212
213 bangTimeMillis = updateTimeMillis;
214
215 bangAudioClip.play ( );
216
217 if ( state != STATE_BOOM )
218 {
219 state = STATE_BANG;
220
221 setIcon ( bangIcon );
222 }
223 }
224 else if ( state == STATE_BOOM )
225 {
226 if ( updateTimeMillis >= boomTimeMillis + RECOVERY_PERIOD_MILLIS )
227 {
228 setIcon ( greenIcon );
229
230 state = STATE_GREEN;
231 }
232 }
233 else if ( ( state == STATE_BANG )
234 || ( state == STATE_RED )
235 || ( state == STATE_YELLOW ) )
236 {
237 if ( updateTimeMillis >= bangTimeMillis + rechargePeriodMillis )
238 {
239 setIcon ( greenIcon );
240
241 state = STATE_GREEN;
242 }
243 else if (
244 updateTimeMillis >= bangTimeMillis + rechargePeriodMillis / 2 )
245 {
246 setIcon ( yellowIcon );
247
248 state = STATE_YELLOW;
249 }
250 else if (
251 updateTimeMillis >= bangTimeMillis + BANG_PERIOD_MILLIS )
252 {
253 setIcon ( redIcon );
254
255 state = STATE_RED;
256 }
257 }
258
259 double x = getX ( );
260
261 double velocity = getVelocity ( );
262
263 Point mousePoint = this.mousePoint;
264
265 if ( mousePoint != null )
266 {
267 double delta = mousePoint.x - dodgerHalfWidth - x;
268
269 if ( delta > 0 )
270 {
271 if ( velocity > delta / 2 )
272 {
273 velocity = delta / 2;
274 }
275 else if ( velocity < 0 )
276 {
277 velocity = velocity / 2 + 1;
278 }
279 else
280 {
281 velocity++;
282 }
283 }
284 else if ( delta < 0 )
285 {
286 if ( velocity < delta / 2 )
287 {
288 velocity = delta / 2;
289 }
290 else if ( velocity > 0 )
291 {
292 velocity = velocity / 2 - 1;
293 }
294 else
295 {
296 velocity--;
297 }
298 }
299 else
300 {
301 velocity = 0;
302 }
303
304 x += velocity;
305
306 x = x < -dodgerHalfWidth ? -dodgerHalfWidth : x;
307
308 x = x > bounds.width - dodgerHalfWidth
309 ? bounds.width - dodgerHalfWidth : x;
310
311 setX ( x );
312
313 setY ( bounds.height - dodgerVerticalOffset );
314
315 setVelocity ( velocity );
316 }
317 }
318
319 //////////////////////////////////////////////////////////////////////
320 //////////////////////////////////////////////////////////////////////
321
322 /*
323 public void paint (
324 JComponent component,
325 Graphics2D graphics,
326 int offsetX,
327 int offsetY )
328 //////////////////////////////////////////////////////////////////////
329 {
330 super.paint ( component, graphics, offsetX, offsetY );
331
332 if ( shielded )
333 {
334 graphics.setColor ( Color.BLACK );
335
336 getPaintBounds ( paintBounds );
337
338 graphics.drawRect (
339 paintBounds.x,
340 paintBounds.y,
341 paintBounds.width,
342 paintBounds.height );
343 }
344 }
345 */
346
347 //////////////////////////////////////////////////////////////////////
348 //////////////////////////////////////////////////////////////////////
349
350 public void mouseClicked ( MouseEvent mouseEvent )
351 //////////////////////////////////////////////////////////////////////
352 {
353 }
354
355 public void mouseDragged ( MouseEvent mouseEvent )
356 //////////////////////////////////////////////////////////////////////
357 {
358 mousePoint = mouseEvent.getPoint ( );
359
360 lastMoveTimeMillis = System.currentTimeMillis ( );
361 }
362
363 public void mouseEntered ( MouseEvent mouseEvent )
364 //////////////////////////////////////////////////////////////////////
365 {
366 }
367
368 public void mouseExited ( MouseEvent mouseEvent )
369 //////////////////////////////////////////////////////////////////////
370 {
371 }
372
373 public void mouseMoved ( MouseEvent mouseEvent )
374 //////////////////////////////////////////////////////////////////////
375 {
376 mousePoint = mouseEvent.getPoint ( );
377
378 lastMoveTimeMillis = System.currentTimeMillis ( );
379 }
380
381 public void mousePressed ( MouseEvent mouseEvent )
382 //////////////////////////////////////////////////////////////////////
383 {
384 bang = true;
385
386 lastMoveTimeMillis = System.currentTimeMillis ( );
387 }
388
389 public void mouseReleased ( MouseEvent mouseEvent )
390 //////////////////////////////////////////////////////////////////////
391 {
392 bang = false;
393
394 lastMoveTimeMillis = System.currentTimeMillis ( );
395 }
396
397 //////////////////////////////////////////////////////////////////////
398 //////////////////////////////////////////////////////////////////////
399
400 public void keyPressed ( KeyEvent keyEvent )
401 //////////////////////////////////////////////////////////////////////
402 {
403 bang = true;
404
405 lastMoveTimeMillis = System.currentTimeMillis ( );
406 }
407
408 public void keyReleased ( KeyEvent keyEvent )
409 //////////////////////////////////////////////////////////////////////
410 {
411 bang = false;
412
413 lastMoveTimeMillis = System.currentTimeMillis ( );
414 }
415
416 public void keyTyped ( KeyEvent keyEvent )
417 //////////////////////////////////////////////////////////////////////
418 {
419 }
420
421 //////////////////////////////////////////////////////////////////////
422 //////////////////////////////////////////////////////////////////////
423 }