001         package com.croftsoft.apps.cyborg;
002         
003         import java.awt.*;
004         import java.awt.event.*;
005         import javax.swing.*;
006         
007         import com.croftsoft.core.animation.*;
008         import com.croftsoft.core.animation.animator.FrameRateAnimator;
009         import com.croftsoft.core.lang.NullArgumentException;
010         import com.croftsoft.core.lang.lifecycle.Initializable;
011         
012         /*********************************************************************
013         * Graphical representation of the model.
014         * 
015         * @version
016         *   $Date: 2008/04/19 21:30:59 $
017         * @since
018         *   2005-03-16
019         * @author
020         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
021         *********************************************************************/
022    
023         public final class  CyborgAnimator     
024           implements ComponentAnimator, Initializable
025         //////////////////////////////////////////////////////////////////////
026         //////////////////////////////////////////////////////////////////////
027         {
028           
029         private static final Color
030           BACKGROUND = Color.WHITE,
031           FOREGROUND = Color.BLACK;
032         
033         private static final int
034           OFFSET_X      =  60,
035           SQUARE_HALF   = 100,
036           OFFSET_Y_TOP  =  10,
037           OFFSET_Y      = OFFSET_Y_TOP + 2 * SQUARE_HALF + 10,
038           CURSOR_RADIUS =  10,
039           OFFSET_SPIKES = OFFSET_Y + 2 * SQUARE_HALF;
040         
041         //
042         
043         private final CyborgModel  cyborgModel;
044         
045         private final Component    component;
046           
047         private final Rectangle    componentBounds;
048         
049         //
050         
051         private boolean            componentResized;
052           
053         private FrameRateAnimator  frameRateAnimator;
054         
055         //////////////////////////////////////////////////////////////////////
056         //////////////////////////////////////////////////////////////////////
057         
058         public static int  fromX ( double  x )
059         //////////////////////////////////////////////////////////////////////
060         {
061           return ( int ) ( SQUARE_HALF * x ) + OFFSET_X + SQUARE_HALF;
062         }
063         
064         public static int  fromY ( double  y )
065         //////////////////////////////////////////////////////////////////////
066         {
067           return ( int ) ( -SQUARE_HALF * y ) + OFFSET_Y + SQUARE_HALF;
068         }
069         
070         public static double  toX ( int  x )
071         //////////////////////////////////////////////////////////////////////
072         {
073           return ( x - OFFSET_X - SQUARE_HALF ) / ( double ) SQUARE_HALF;
074         }
075         
076         public static double  toY ( int  y )
077         //////////////////////////////////////////////////////////////////////
078         {
079           return -( y - OFFSET_Y - SQUARE_HALF ) / ( double ) SQUARE_HALF;
080         }
081         
082         //////////////////////////////////////////////////////////////////////
083         //////////////////////////////////////////////////////////////////////
084         
085         public  CyborgAnimator (
086           CyborgModel  cyborgModel,
087           Component    component )
088         //////////////////////////////////////////////////////////////////////
089         {
090           NullArgumentException.check ( this.cyborgModel = cyborgModel );
091           
092           NullArgumentException.check ( this.component   = component   );       
093           
094           component.requestFocus ( );
095           
096           component.addComponentListener (
097             new ComponentAdapter ( )
098             {
099               public void  componentResized ( ComponentEvent  componentEvent )
100               {
101                 componentResized = true;
102               }
103             } );
104           
105           componentBounds  = new Rectangle ( );
106           
107           componentResized = true;
108         }
109           
110         //////////////////////////////////////////////////////////////////////
111         //////////////////////////////////////////////////////////////////////
112         
113         public void  init ( )
114         //////////////////////////////////////////////////////////////////////
115         {
116           frameRateAnimator = new FrameRateAnimator ( component ); 
117         }
118         
119         public void  update ( JComponent  jComponent )
120         //////////////////////////////////////////////////////////////////////
121         {
122           if ( componentResized )
123           {
124             componentResized = false;
125             
126             jComponent.repaint ( );
127             
128             jComponent.getBounds ( componentBounds );
129             
130             componentBounds.x = 0;
131           }
132           
133           frameRateAnimator.update ( jComponent );
134           
135           if ( cyborgModel.getAnimate ( ) )
136           {       
137             jComponent.repaint ( );
138           }
139         }     
140         
141         public void  paint (
142           JComponent  jComponent,
143           Graphics2D  graphics2D )
144         //////////////////////////////////////////////////////////////////////
145         {
146           graphics2D.setColor ( BACKGROUND );
147           
148           graphics2D.fill ( componentBounds );
149           
150           graphics2D.setColor ( FOREGROUND );
151           
152           double  x = cyborgModel.getX ( );
153           
154           double  y = cyborgModel.getY ( );
155           
156           double  aimX = cyborgModel.getAimX ( );
157           
158           double  aimY = cyborgModel.getAimY ( );
159           
160           String  text = String.format (
161             "%1$+1.3f %2$+1.3f%n",
162             new Object [ ] {
163               new Double ( aimX ),
164               new Double ( aimY ) } );
165           
166           graphics2D.drawString ( text, OFFSET_X, OFFSET_SPIKES + 225 );
167           
168           text = String.format (
169             "%1$+1.3f %2$+1.3f%n",
170             new Object [ ] {
171               new Double ( x ),
172               new Double ( y ) } );
173           
174           graphics2D.drawString ( text, OFFSET_X, OFFSET_SPIKES + 250 );
175           
176           boolean [ ] [ ]  spikeRasters = cyborgModel.getSpikeRasters ( );
177           
178           for ( int  i = 0; i < spikeRasters.length; i++ )
179           {
180             boolean [ ]  spikeRaster = spikeRasters [ i ];
181             
182             graphics2D.drawLine (
183               OFFSET_X,
184               OFFSET_SPIKES + 20 + i * 50,
185               OFFSET_X + spikeRaster.length - 1,
186               OFFSET_SPIKES + 20 + i * 50 );
187             
188             int  spikeCount = 0;
189             
190             for ( int  j = 0; j < spikeRaster.length; j++ )
191             {
192               if ( spikeRaster [ j ] )
193               {
194                 spikeCount++;
195                 
196                 graphics2D.drawLine (
197                   OFFSET_X + j,
198                   OFFSET_SPIKES + 20 + i * 50,
199                   OFFSET_X + j,
200                   OFFSET_SPIKES + 20 + i * 50 - 10 );
201               }
202             }
203             
204             String  rate = Integer.toString ( spikeCount );
205             
206             graphics2D.drawString (
207               rate,
208               OFFSET_X,
209               OFFSET_SPIKES + 40 + i * 50 );
210           }
211           
212           graphics2D.drawRect (
213             OFFSET_X, OFFSET_Y_TOP, 2 * SQUARE_HALF, 2 * SQUARE_HALF );
214           
215           graphics2D.drawRect (
216             OFFSET_X, OFFSET_Y, 2 * SQUARE_HALF, 2 * SQUARE_HALF );
217           
218           graphics2D.drawOval (
219             fromX ( x ) - CURSOR_RADIUS,
220             fromY ( y ) - CURSOR_RADIUS - ( OFFSET_Y - OFFSET_Y_TOP ),
221             2 * CURSOR_RADIUS,
222             2 * CURSOR_RADIUS );
223           
224           int  targetRadius
225             = ( int ) ( 2 * SQUARE_HALF * cyborgModel.getTargetRadius ( ) );
226           
227           int  targetCenterX
228             = fromX ( cyborgModel.getTargetCenterX ( ) );
229           
230           int  targetCenterY
231             = fromY ( cyborgModel.getTargetCenterY ( ) );
232           
233           graphics2D.drawOval (
234             targetCenterX - targetRadius,
235             targetCenterY - targetRadius - ( OFFSET_Y - OFFSET_Y_TOP ),
236             2 * targetRadius,
237             2 * targetRadius );
238           
239           graphics2D.drawLine (
240             fromX ( 0.0 ),
241             fromY ( 0.0 ),
242             fromX ( aimX ),
243             fromY ( aimY ) );
244           
245           frameRateAnimator.paint ( jComponent, graphics2D );
246         }     
247         
248         //////////////////////////////////////////////////////////////////////
249         //////////////////////////////////////////////////////////////////////
250         }