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 }