001 package com.croftsoft.apps.ajgp.basics;
002
003 import java.applet.Applet;
004 import java.applet.AudioClip;
005 import java.awt.Color;
006 import java.awt.Cursor;
007 import java.awt.Dimension;
008 import java.awt.Font;
009 import java.awt.Graphics2D;
010 import java.awt.Point;
011 import java.awt.Rectangle;
012 import java.awt.event.ComponentAdapter;
013 import java.awt.event.ComponentEvent;
014 import java.awt.event.KeyAdapter;
015 import java.awt.event.KeyEvent;
016 import java.awt.event.MouseAdapter;
017 import java.awt.event.MouseEvent;
018 import java.awt.event.MouseMotionAdapter;
019 import java.util.Random;
020 import javax.swing.Icon;
021 import javax.swing.ImageIcon;
022 import javax.swing.JComponent;
023
024 import com.croftsoft.core.CroftSoftConstants;
025 import com.croftsoft.core.animation.AnimatedApplet;
026 import com.croftsoft.core.animation.AnimationInit;
027
028 /*********************************************************************
029 * Game programming basics example.
030 *
031 * @version
032 * 2003-11-06
033 * @since
034 * 2003-10-05
035 * @author
036 * <a href="https://www.croftsoft.com/">David Wallace Croft</a>
037 *********************************************************************/
038
039 public final class BasicsExample
040 extends AnimatedApplet
041 //////////////////////////////////////////////////////////////////////
042 //////////////////////////////////////////////////////////////////////
043 {
044
045 private static final String VERSION
046 = "2003-11-06";
047
048 private static final String TITLE
049 = "CroftSoft Basics";
050
051 private static final String APPLET_INFO
052 = "\n" + TITLE + "\n"
053 + "Version " + VERSION + "\n"
054 + CroftSoftConstants.COPYRIGHT + "\n"
055 + CroftSoftConstants.DEFAULT_LICENSE + "\n"
056 + CroftSoftConstants.HOME_PAGE + "\n";
057
058 //
059
060 private static final Color BACKGROUND_COLOR
061 = Color.BLACK;
062
063 private static final Cursor CURSOR
064 = new Cursor ( Cursor.CROSSHAIR_CURSOR );
065
066 private static final Font FONT
067 = new Font ( "Arioso", Font.BOLD, 20 );
068
069 private static final Double FRAME_RATE
070 = new Double ( 30.0 );
071
072 private static final Dimension FRAME_SIZE
073 = new Dimension ( 600, 400 );
074
075 private static final String SHUTDOWN_CONFIRMATION_PROMPT
076 = "Close " + TITLE + "?";
077
078 //
079
080 private static final String MEDIA_DIR = "media/basics/";
081
082 private static final String AUDIO_FILENAME
083 = MEDIA_DIR + "drip.wav";
084
085 private static final String IMAGE_FILENAME
086 = MEDIA_DIR + "croftsoft.png";
087
088 //
089
090 private static final long RANDOM_SEED = 0L;
091
092 private static final Color BALL_COLOR = Color.RED;
093
094 private static final Color SCORE_COLOR = Color.GREEN;
095
096 private static final int VELOCITY = 3;
097
098 //////////////////////////////////////////////////////////////////////
099 // final instance variables
100 //////////////////////////////////////////////////////////////////////
101
102 private final Rectangle componentBounds;
103
104 private final Random random;
105
106 //
107
108 private final Rectangle ballRectangle;
109
110 private final Rectangle targetRectangle;
111
112 //////////////////////////////////////////////////////////////////////
113 // non-final instance variables
114 //////////////////////////////////////////////////////////////////////
115
116 private boolean componentResized;
117
118 private KeyEvent keyEvent;
119
120 private Point mousePoint;
121
122 private boolean mousePressed;
123
124 //
125
126 private AudioClip audioClip;
127
128 private Icon icon;
129
130 //
131
132 private boolean rolling;
133
134 private int score;
135
136 //////////////////////////////////////////////////////////////////////
137 //////////////////////////////////////////////////////////////////////
138
139 public static void main ( String [ ] args )
140 //////////////////////////////////////////////////////////////////////
141 {
142 launch ( new BasicsExample ( ) );
143 }
144
145 private static AnimationInit createAnimationInit ( )
146 //////////////////////////////////////////////////////////////////////
147 {
148 AnimationInit animationInit = new AnimationInit ( );
149
150 animationInit.setAppletInfo ( APPLET_INFO );
151
152 animationInit.setCursor ( CURSOR );
153
154 animationInit.setFont ( FONT );
155
156 animationInit.setFrameIconFilename ( IMAGE_FILENAME );
157
158 animationInit.setFrameRate ( FRAME_RATE );
159
160 animationInit.setFrameSize ( FRAME_SIZE );
161
162 animationInit.setFrameTitle ( TITLE );
163
164 animationInit.setShutdownConfirmationPrompt (
165 SHUTDOWN_CONFIRMATION_PROMPT );
166
167 return animationInit;
168 }
169
170 //////////////////////////////////////////////////////////////////////
171 //////////////////////////////////////////////////////////////////////
172
173 public BasicsExample ( )
174 //////////////////////////////////////////////////////////////////////
175 {
176 super ( createAnimationInit ( ) );
177
178 componentBounds = new Rectangle ( );
179
180 random = new Random ( RANDOM_SEED );
181
182 animatedComponent.addComponentListener (
183 new ComponentAdapter ( )
184 {
185 public void componentResized (
186 ComponentEvent componentEvent )
187 {
188 componentResized = true;
189 }
190 } );
191
192 animatedComponent.addKeyListener (
193 new KeyAdapter ( )
194 {
195 public void keyPressed ( KeyEvent ke )
196 {
197 keyEvent = ke;
198 }
199 } );
200
201 animatedComponent.addMouseListener (
202 new MouseAdapter ( )
203 {
204 public void mousePressed ( MouseEvent mouseEvent )
205 {
206 mousePressed = true;
207 }
208 } );
209
210 animatedComponent.addMouseMotionListener (
211 new MouseMotionAdapter ( )
212 {
213 public void mouseMoved ( MouseEvent mouseEvent )
214 {
215 mousePoint = mouseEvent.getPoint ( );
216 }
217 } );
218
219 ballRectangle = new Rectangle ( );
220
221 targetRectangle = new Rectangle ( );
222 }
223
224 //////////////////////////////////////////////////////////////////////
225 // interface Lifecycle methods
226 //////////////////////////////////////////////////////////////////////
227
228 public void init ( )
229 //////////////////////////////////////////////////////////////////////
230 {
231 super.init ( );
232
233 animatedComponent.requestFocus ( );
234
235 componentResized = true;
236
237 ClassLoader classLoader = getClass ( ).getClassLoader ( );
238
239 audioClip = Applet.newAudioClip (
240 classLoader.getResource ( AUDIO_FILENAME ) );
241
242 icon = new ImageIcon (
243 classLoader.getResource ( IMAGE_FILENAME ) );
244
245 ballRectangle.width = icon.getIconWidth ( );
246
247 ballRectangle.height = icon.getIconHeight ( );
248
249 targetRectangle.width = icon.getIconWidth ( );
250
251 targetRectangle.height = icon.getIconHeight ( );
252 }
253
254 //////////////////////////////////////////////////////////////////////
255 // interface ComponentAnimator methods
256 //////////////////////////////////////////////////////////////////////
257
258 public void update ( JComponent component )
259 //////////////////////////////////////////////////////////////////////
260 {
261 if ( componentResized )
262 {
263 componentResized = false;
264
265 component.repaint ( );
266
267 component.getBounds ( componentBounds );
268
269 if ( !rolling )
270 {
271 ballRectangle.y = componentBounds.height - ballRectangle.height;
272 }
273 }
274
275 boolean rollRequested = false;
276
277 if ( mousePressed )
278 {
279 mousePressed = false;
280
281 rollRequested = true;
282 }
283
284 int ballMove = 0;
285
286 if ( keyEvent != null )
287 {
288 int keyCode = keyEvent.getKeyCode ( );
289
290 switch ( keyCode )
291 {
292 case KeyEvent.VK_SPACE:
293
294 rollRequested = true;
295
296 break;
297
298 case KeyEvent.VK_LEFT:
299 case KeyEvent.VK_KP_LEFT:
300
301 ballMove = -1;
302
303 break;
304
305 case KeyEvent.VK_RIGHT:
306 case KeyEvent.VK_KP_RIGHT:
307
308 ballMove = 1;
309
310 break;
311 }
312
313 keyEvent = null;
314
315 mousePoint = null;
316 }
317
318 if ( mousePoint != null )
319 {
320 if ( mousePoint.x
321 < ballRectangle.x + ballRectangle.width / 2 - VELOCITY)
322 {
323 ballMove = -1;
324 }
325 else if ( mousePoint.x
326 > ballRectangle.x + ballRectangle.width / 2 + VELOCITY )
327 {
328 ballMove = 1;
329 }
330 else
331 {
332 mousePoint = null;
333 }
334 }
335
336 if ( rollRequested )
337 {
338 if ( !rolling )
339 {
340 audioClip.play ( );
341
342 rolling = true;
343 }
344 }
345
346 component.repaint ( targetRectangle );
347
348 if ( rolling )
349 {
350 component.repaint ( ballRectangle );
351
352 ballRectangle.y -= VELOCITY;
353
354 boolean reset = false;
355
356 if ( targetRectangle.intersects ( ballRectangle ) )
357 {
358 reset = true;
359
360 targetRectangle.x = -targetRectangle.width;
361
362 audioClip.play ( );
363
364 score++;
365
366 component.repaint ( );
367 }
368 else if ( ballRectangle.y + ballRectangle.height < 0 )
369 {
370 reset = true;
371
372 if ( score > 0 )
373 {
374 score--;
375 }
376
377 component.repaint ( );
378 }
379
380 if ( reset )
381 {
382 ballRectangle.y = componentBounds.height - ballRectangle.height;
383
384 rolling = false;
385 }
386
387 component.repaint ( ballRectangle );
388 }
389 else if ( ballMove != 0 )
390 {
391 component.repaint ( ballRectangle );
392
393 ballRectangle.x += ballMove * VELOCITY;
394
395 if ( ballRectangle.x < 0 )
396 {
397 ballRectangle.x = 0;
398 }
399
400 if ( ballRectangle.x
401 > componentBounds.width - ballRectangle.width )
402 {
403 ballRectangle.x
404 = componentBounds.width - ballRectangle.width;
405 }
406
407 component.repaint ( ballRectangle );
408 }
409
410 if ( score > 1 )
411 {
412 targetRectangle.x += random.nextInt ( score ) * VELOCITY;
413 }
414 else
415 {
416 targetRectangle.x += VELOCITY;
417 }
418
419 if ( targetRectangle.x >= componentBounds.width )
420 {
421 targetRectangle.x = -targetRectangle.width;
422 }
423
424 component.repaint ( targetRectangle );
425 }
426
427 public void paint (
428 JComponent component,
429 Graphics2D graphics )
430 //////////////////////////////////////////////////////////////////////
431 {
432 graphics.setColor ( BACKGROUND_COLOR );
433
434 graphics.fill ( componentBounds );
435
436 icon.paintIcon ( component, graphics, targetRectangle.x, 0 );
437
438 graphics.setColor ( BALL_COLOR );
439
440 graphics.fillOval (
441 ballRectangle.x,
442 ballRectangle.y,
443 ballRectangle.width,
444 ballRectangle.height );
445
446 graphics.setColor ( SCORE_COLOR );
447
448 graphics.drawString (
449 "Score: " + Integer.toString ( score ),
450 0, componentBounds.height );
451 }
452
453 //////////////////////////////////////////////////////////////////////
454 //////////////////////////////////////////////////////////////////////
455 }