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         }