001 package com.croftsoft.apps.mars.model.seri; 002 003 import java.awt.*; 004 import java.awt.geom.Ellipse2D; 005 import java.util.Random; 006 007 import com.croftsoft.core.lang.NullArgumentException; 008 import com.croftsoft.core.math.geom.Circle; 009 import com.croftsoft.core.math.geom.PointXY; 010 011 import com.croftsoft.apps.mars.model.Obstacle; 012 import com.croftsoft.apps.mars.model.World; 013 014 /********************************************************************* 015 * An obstacle. 016 * 017 * @version 018 * 2003-05-11 019 * @since 020 * 2003-03-30 021 * @author 022 * <a href="https://www.croftsoft.com/">David Wallace Croft</a> 023 *********************************************************************/ 024 025 public final class SeriObstacle 026 extends SeriModel 027 implements Obstacle 028 ////////////////////////////////////////////////////////////////////// 029 ////////////////////////////////////////////////////////////////////// 030 { 031 032 private static final long serialVersionUID = 0L; 033 034 // 035 036 private static final double Z = 0.2; 037 038 private static final double DRIFT_RATE = 1.0; 039 040 private static final double SPEED_MAX = 1.0; 041 042 // 043 044 private final World world; 045 046 private final Circle circle; 047 048 private final Random random; 049 050 private final Rectangle driftBounds; 051 052 private final double radiusMin; 053 054 // 055 056 private boolean active; 057 058 private boolean updated; 059 060 private double velocityX; 061 062 private double velocityY; 063 064 ////////////////////////////////////////////////////////////////////// 065 // constructor methods 066 ////////////////////////////////////////////////////////////////////// 067 068 public SeriObstacle ( 069 World world, 070 double centerX, 071 double centerY, 072 double radius, 073 double radiusMin, 074 Random random, 075 Rectangle driftBounds ) 076 ////////////////////////////////////////////////////////////////////// 077 { 078 NullArgumentException.check ( this.world = world ); 079 080 circle = new Circle ( centerX, centerY, radius ); 081 082 this.radiusMin = radiusMin; 083 084 NullArgumentException.check ( this.random = random ); 085 086 NullArgumentException.check ( this.driftBounds = driftBounds ); 087 088 active = true; 089 090 updated = true; 091 } 092 093 ////////////////////////////////////////////////////////////////////// 094 // interface Model methods 095 ////////////////////////////////////////////////////////////////////// 096 097 public boolean isActive ( ) { return active; } 098 099 public Shape getShape ( ) { return circle; } 100 101 public boolean isUpdated ( ) { return updated; } 102 103 public double getZ ( ) { return Z; } 104 105 public void setCenter ( 106 double x, 107 double y ) 108 ////////////////////////////////////////////////////////////////////// 109 { 110 circle.setCenter ( x, y ); 111 } 112 113 public void prepare ( ) 114 ////////////////////////////////////////////////////////////////////// 115 { 116 updated = false; 117 } 118 119 public void update ( double timeDelta ) 120 ////////////////////////////////////////////////////////////////////// 121 { 122 if ( !active ) 123 { 124 return; 125 } 126 127 velocityX 128 += DRIFT_RATE * timeDelta * ( 2.0 * random.nextDouble ( ) - 1.0 ); 129 130 velocityY 131 += DRIFT_RATE * timeDelta * ( 2.0 * random.nextDouble ( ) - 1.0 ); 132 133 if ( velocityX > SPEED_MAX ) 134 { 135 velocityX = SPEED_MAX; 136 } 137 else if ( velocityX < -SPEED_MAX ) 138 { 139 velocityX = -SPEED_MAX; 140 } 141 142 if ( velocityY > SPEED_MAX ) 143 { 144 velocityY = SPEED_MAX; 145 } 146 else if ( velocityY < -SPEED_MAX ) 147 { 148 velocityY = -SPEED_MAX; 149 } 150 151 PointXY center = circle.getCenter ( ); 152 153 double oldCenterX = center.getX ( ); 154 155 double oldCenterY = center.getY ( ); 156 157 double destinationX = oldCenterX + velocityX * timeDelta; 158 159 double destinationY = oldCenterY + velocityY * timeDelta; 160 161 double radius = circle.getRadius ( ); 162 163 double minX = driftBounds.getX ( ) + radius; 164 165 double minY = driftBounds.getY ( ) + radius; 166 167 double maxX = driftBounds.getWidth ( ) - radius; 168 169 double maxY = driftBounds.getHeight ( ) - radius; 170 171 if ( destinationX < minX ) 172 { 173 destinationX = minX; 174 175 velocityX = -velocityX; 176 } 177 else if ( destinationX > maxX ) 178 { 179 destinationX = maxX; 180 181 velocityX = -velocityX; 182 } 183 184 if ( destinationY < minY ) 185 { 186 destinationY = minY; 187 188 velocityY = -velocityY; 189 } 190 else if ( destinationY > maxY ) 191 { 192 destinationY = maxY; 193 194 velocityY = -velocityY; 195 } 196 197 if ( ( destinationX != oldCenterX ) 198 || ( destinationY != oldCenterY ) ) 199 { 200 circle.setCenter ( destinationX, destinationY ); 201 202 if ( world.isBlocked ( this ) ) 203 { 204 circle.setCenter ( oldCenterX, oldCenterY ); 205 } 206 else 207 { 208 updated = true; 209 } 210 } 211 } 212 213 ////////////////////////////////////////////////////////////////////// 214 // interface Damageable method 215 ////////////////////////////////////////////////////////////////////// 216 217 public void addDamage ( double damage ) 218 ////////////////////////////////////////////////////////////////////// 219 { 220 if ( !active 221 || ( damage == 0.0 ) ) 222 { 223 return; 224 } 225 226 updated = true; 227 228 double radius = circle.getRadius ( ) - damage; 229 230 if ( radius < radiusMin ) 231 { 232 active = false; 233 } 234 else 235 { 236 circle.setRadius ( radius ); 237 } 238 } 239 240 ////////////////////////////////////////////////////////////////////// 241 // interface Obstacle methods 242 ////////////////////////////////////////////////////////////////////// 243 244 public void setActive ( boolean active ) 245 ////////////////////////////////////////////////////////////////////// 246 { 247 this.active = active; 248 } 249 250 public void setRadius ( double radius ) 251 ////////////////////////////////////////////////////////////////////// 252 { 253 circle.setRadius ( radius ); 254 } 255 256 ////////////////////////////////////////////////////////////////////// 257 ////////////////////////////////////////////////////////////////////// 258 }