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.util.Random; 008 import javax.swing.*; 009 import javax.swing.event.*; 010 011 import com.croftsoft.core.lang.NullArgumentException; 012 import com.croftsoft.core.animation.*; 013 import com.croftsoft.core.animation.sprite.*; 014 015 /********************************************************************* 016 * An IconSprite subclass representing a Dodger obstacle. 017 * 018 * @version 019 * 2002-03-23 020 * @since 021 * 2002-03-18 022 * @author 023 * <a href="https://www.croftsoft.com/">David Wallace Croft</a> 024 *********************************************************************/ 025 026 public class ObstacleSprite 027 extends AbstractSprite 028 ////////////////////////////////////////////////////////////////////// 029 ////////////////////////////////////////////////////////////////////// 030 { 031 032 private static final int OBSTACLE_WIDTH = 32; 033 034 private static final int OBSTACLE_HEIGHT = 32; 035 036 private static final long EXPLODE_PERIOD_MILLIS = 1000; 037 038 // 039 040 private final AudioClip explodeAudioClip; 041 042 private final Random random; 043 044 private final Rectangle bounds; 045 046 private final int pixelsPerFrame; 047 048 private final Rectangle paintBounds; 049 050 // 051 052 private Color color; 053 054 private long explodeTimeMillis; 055 056 private boolean hit; 057 058 private boolean exploding; 059 060 ////////////////////////////////////////////////////////////////////// 061 // constructor methods 062 ////////////////////////////////////////////////////////////////////// 063 064 065 public ObstacleSprite ( 066 AudioClip explodeAudioClip, 067 Random random, 068 Rectangle bounds, 069 int pixelsPerFrame ) 070 ////////////////////////////////////////////////////////////////////// 071 { 072 NullArgumentException.check ( 073 this.explodeAudioClip = explodeAudioClip ); 074 075 NullArgumentException.check ( this.random = random ); 076 077 NullArgumentException.check ( this.bounds = bounds ); 078 079 this.pixelsPerFrame = pixelsPerFrame; 080 081 paintBounds = new Rectangle ( 082 0, 0, OBSTACLE_WIDTH, OBSTACLE_HEIGHT ); 083 084 setY ( Double.POSITIVE_INFINITY ); 085 086 color = new Color ( 087 random.nextInt ( 256 ), 088 random.nextInt ( 256 ), 089 random.nextInt ( 256 ) ); 090 } 091 092 ////////////////////////////////////////////////////////////////////// 093 // accessor methods 094 ////////////////////////////////////////////////////////////////////// 095 096 public void getPaintBounds ( Rectangle paintBounds ) 097 ////////////////////////////////////////////////////////////////////// 098 { 099 paintBounds.setBounds ( this.paintBounds ); 100 } 101 102 public Shape getCollisionShape ( ) 103 ////////////////////////////////////////////////////////////////////// 104 { 105 if ( exploding ) 106 { 107 return null; 108 } 109 110 return paintBounds; 111 } 112 113 ////////////////////////////////////////////////////////////////////// 114 // mutator methods 115 ////////////////////////////////////////////////////////////////////// 116 117 public void setX ( double x ) 118 ////////////////////////////////////////////////////////////////////// 119 { 120 super.setX ( x ); 121 122 paintBounds.x = ( int ) Math.round ( x ); 123 } 124 125 public void setY ( double y ) 126 ////////////////////////////////////////////////////////////////////// 127 { 128 super.setY ( y ); 129 130 paintBounds.y = ( int ) Math.round ( y ); 131 } 132 133 public void setHit ( ) 134 ////////////////////////////////////////////////////////////////////// 135 { 136 hit = true; 137 } 138 139 public void reset ( ) 140 ////////////////////////////////////////////////////////////////////// 141 { 142 hit = false; 143 144 exploding = false; 145 146 setX ( -OBSTACLE_WIDTH 147 + random.nextInt ( bounds.width + OBSTACLE_WIDTH ) ); 148 149 setY ( -random.nextInt ( bounds.height ) - OBSTACLE_HEIGHT ); 150 151 color = new Color ( 152 random.nextInt ( 256 ), 153 random.nextInt ( 256 ), 154 random.nextInt ( 256 ) ); 155 } 156 157 ////////////////////////////////////////////////////////////////////// 158 // interface ComponentAnimator methods 159 ////////////////////////////////////////////////////////////////////// 160 161 public void update ( JComponent component ) 162 ////////////////////////////////////////////////////////////////////// 163 { 164 long updateTimeMillis = System.currentTimeMillis ( ); 165 166 double y = getY ( ); 167 168 y += pixelsPerFrame; 169 170 if ( y >= bounds.height ) 171 { 172 reset ( ); 173 } 174 else 175 { 176 setY ( y ); 177 } 178 179 if ( exploding ) 180 { 181 if ( updateTimeMillis 182 >= explodeTimeMillis + EXPLODE_PERIOD_MILLIS ) 183 { 184 reset ( ); 185 } 186 187 color = new Color ( 188 random.nextInt ( 256 ), 189 random.nextInt ( 256 ), 190 random.nextInt ( 256 ) ); 191 } 192 else if ( hit ) 193 { 194 explodeAudioClip.play ( ); 195 196 color = new Color ( 197 random.nextInt ( 256 ), 198 random.nextInt ( 256 ), 199 random.nextInt ( 256 ) ); 200 201 explodeTimeMillis = updateTimeMillis; 202 203 exploding = true; 204 } 205 } 206 207 public void paint ( 208 JComponent component, 209 Graphics2D graphics ) 210 ////////////////////////////////////////////////////////////////////// 211 { 212 graphics.setColor ( color ); 213 214 graphics.fillRect ( 215 paintBounds.x, 216 paintBounds.y, 217 OBSTACLE_WIDTH, 218 OBSTACLE_HEIGHT ); 219 220 graphics.setColor ( Color.BLACK ); 221 222 graphics.drawRect ( 223 paintBounds.x, 224 paintBounds.y, 225 OBSTACLE_WIDTH, 226 OBSTACLE_HEIGHT ); 227 } 228 229 ////////////////////////////////////////////////////////////////////// 230 ////////////////////////////////////////////////////////////////////// 231 }