Rev 956 | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 886 | chris | 1 | package com.gebauz.burutaru.game.entities; |
| 2 | |||
| 890 | chris | 3 | import com.badlogic.gdx.audio.Sound; |
| 886 | chris | 4 | import com.gebauz.bauzoid.graphics.sprite.AtlasSprite; |
| 915 | chris | 5 | import com.gebauz.bauzoid.graphics.sprite.AtlasSpriteFrame; |
| 945 | chris | 6 | import com.gebauz.bauzoid.graphics.sprite.AtlasSpriteInstance; |
| 886 | chris | 7 | import com.gebauz.bauzoid.math.MathUtil; |
| 945 | chris | 8 | import com.gebauz.bauzoid.math.Matrix4; |
| 887 | chris | 9 | import com.gebauz.bauzoid.math.Vector2; |
| 950 | chris | 10 | import com.gebauz.bauzoid.math.collision.AABoundingBox; |
| 945 | chris | 11 | import com.gebauz.bauzoid.math.collision.Shape; |
| 12 | import com.gebauz.bauzoid.math.collision.ShapeUtil; |
||
| 886 | chris | 13 | import com.gebauz.burutaru.GameConsts; |
| 14 | import com.gebauz.burutaru.game.GameLogic; |
||
| 15 | |||
| 16 | public class PowerUpMissile extends Entity |
||
| 17 | { |
||
| 18 | |||
| 19 | // Constants======================================================================================== |
||
| 20 | |||
| 945 | chris | 21 | public static final int MISSILE_DAMAGE = 10; |
| 22 | |||
| 890 | chris | 23 | public static final int MAX_MISSILES = 2; |
| 886 | chris | 24 | |
| 25 | public static final int UPPER_MISSILE = 0; |
||
| 26 | public static final int LOWER_MISSILE = 1; |
||
| 27 | |||
| 28 | public static final float MISSILE_WIDTH = 40; |
||
| 29 | public static final float MISSILE_HEIGHT = MISSILE_WIDTH/2; |
||
| 30 | |||
| 31 | public static final float MISSILE_ROTATION_DURATION = 0.5f; |
||
| 32 | |||
| 33 | public static final float MISSILE_SPEED = 400.0f; |
||
| 34 | |||
| 887 | chris | 35 | public static final float LAUNCH_TIME = 0.4f; |
| 886 | chris | 36 | public static final float LAUNCH_SPEED = 100.0f; |
| 887 | chris | 37 | |
| 38 | public static final int NUM_MISSILE_FRAMES = 4; |
||
| 39 | public static final int ROCKET_FIRE_FRAME = 4; |
||
| 40 | |||
| 41 | public static final float ROCKET_FIRE_SIZE = 20; |
||
| 42 | public static final float ROCKET_FIRE_SIZE_VARIANCE = 10; |
||
| 43 | public static final float ROCKET_FIRE_OFFSET = 5; |
||
| 44 | |||
| 895 | chris | 45 | public static final float MAX_ANGLE = 20.0f; |
| 896 | chris | 46 | public static final float ANGULAR_SPEED = 25.0f; |
| 890 | chris | 47 | |
| 896 | chris | 48 | public static final float HEADING_UPDATE_INTERVAL = 0.125f; |
| 886 | chris | 49 | |
| 50 | // Embedded Types=================================================================================== |
||
| 51 | |||
| 52 | public enum MissilePhase |
||
| 53 | { |
||
| 54 | PHASE_LAUNCHING, |
||
| 55 | PHASE_HOAMING |
||
| 56 | } |
||
| 57 | |||
| 945 | chris | 58 | public class Missile extends Projectile |
| 886 | chris | 59 | { |
| 945 | chris | 60 | public AtlasSpriteInstance spriteInstance = null; |
| 61 | |||
| 886 | chris | 62 | public int type = -1; |
| 63 | public float lifeTime = 0.0f; |
||
| 64 | |||
| 65 | private MissilePhase mPhase; |
||
| 945 | chris | 66 | private float angle = 0.0f; |
| 890 | chris | 67 | private float mCurrentAngle = 0.0f; |
| 886 | chris | 68 | |
| 890 | chris | 69 | private float mHeadingUpdateTimer = 0.0f; |
| 70 | |||
| 886 | chris | 71 | public Missile(int _type) |
| 72 | { |
||
| 945 | chris | 73 | super(MISSILE_DAMAGE); |
| 886 | chris | 74 | type = _type; |
| 945 | chris | 75 | |
| 76 | spriteInstance = new AtlasSpriteInstance(getGraphics(), mMissileSprite, mMissileFrames, mMissileShape); |
||
| 77 | setAlive(false); |
||
| 886 | chris | 78 | } |
| 79 | |||
| 945 | chris | 80 | public void launch(float x, float y) |
| 886 | chris | 81 | { |
| 82 | lifeTime = 0.0f; |
||
| 945 | chris | 83 | angle = 0.0f; |
| 890 | chris | 84 | mCurrentAngle = 0.0f; |
| 886 | chris | 85 | mPhase = MissilePhase.PHASE_LAUNCHING; |
| 890 | chris | 86 | mHeadingUpdateTimer = 0.0f; |
| 945 | chris | 87 | |
| 88 | spriteInstance.param.x = x; |
||
| 89 | spriteInstance.param.y = y; |
||
| 90 | spriteInstance.param.w = MISSILE_WIDTH; |
||
| 91 | spriteInstance.param.h = MISSILE_HEIGHT; |
||
| 92 | spriteInstance.param.pivotX = spriteInstance.param.w; |
||
| 93 | spriteInstance.param.pivotY = spriteInstance.param.h / 2; |
||
| 949 | chris | 94 | spriteInstance.param.angle = 0.0f; |
| 945 | chris | 95 | |
| 96 | setAlive(true); |
||
| 886 | chris | 97 | } |
| 98 | |||
| 99 | public void update(float deltaTime) |
||
| 100 | { |
||
| 101 | // search nearest enemy and adjust heading towards it |
||
| 102 | lifeTime += deltaTime; |
||
| 103 | |||
| 104 | switch(mPhase) |
||
| 105 | { |
||
| 106 | case PHASE_LAUNCHING: |
||
| 107 | //float t = MathUtil.clamp((lifeTime / LAUNCH_TIME), 0.0f, 1.0f); |
||
| 108 | |||
| 109 | if (type == UPPER_MISSILE) |
||
| 110 | { |
||
| 945 | chris | 111 | spriteInstance.param.y -= LAUNCH_SPEED * deltaTime; |
| 886 | chris | 112 | } |
| 113 | else if (type == LOWER_MISSILE) |
||
| 114 | { |
||
| 945 | chris | 115 | spriteInstance.param.y += LAUNCH_SPEED * deltaTime; |
| 886 | chris | 116 | } |
| 117 | |||
| 118 | if (lifeTime > LAUNCH_TIME) |
||
| 119 | { |
||
| 120 | mPhase = MissilePhase.PHASE_HOAMING; |
||
| 890 | chris | 121 | mRocketFireSfx.play(0.3f); |
| 886 | chris | 122 | } |
| 123 | break; |
||
| 124 | case PHASE_HOAMING: |
||
| 887 | chris | 125 | // default target: just ahead |
| 945 | chris | 126 | Vector2 target = new Vector2(spriteInstance.param.x + 100.0f, spriteInstance.param.y); |
| 127 | getGameLogic().getNearestEnemyPosition(spriteInstance.param.x, spriteInstance.param.y, target); |
||
| 890 | chris | 128 | |
| 945 | chris | 129 | Vector2 heading = new Vector2(target.x - spriteInstance.param.x, target.y - spriteInstance.param.y); |
| 887 | chris | 130 | |
| 890 | chris | 131 | mHeadingUpdateTimer += deltaTime; |
| 132 | if (mHeadingUpdateTimer > HEADING_UPDATE_INTERVAL) |
||
| 133 | { |
||
| 134 | mHeadingUpdateTimer = 0.0f; |
||
| 135 | angle = MathUtil.radToDeg((float)Math.atan2(-heading.y, heading.x)); |
||
| 136 | } |
||
| 888 | chris | 137 | |
| 890 | chris | 138 | float diff = MathUtil.turnDegrees(angle, mCurrentAngle); |
| 139 | if (diff > MAX_ANGLE) |
||
| 140 | diff = MAX_ANGLE; |
||
| 141 | if (mCurrentAngle > angle) |
||
| 142 | { |
||
| 143 | mCurrentAngle -= diff * deltaTime * ANGULAR_SPEED; |
||
| 144 | if (mCurrentAngle < angle) |
||
| 145 | mCurrentAngle = angle; |
||
| 146 | } |
||
| 147 | else if (mCurrentAngle < angle) |
||
| 148 | { |
||
| 149 | mCurrentAngle += diff * deltaTime * ANGULAR_SPEED; |
||
| 150 | if (mCurrentAngle > angle) |
||
| 151 | mCurrentAngle = angle; |
||
| 152 | } |
||
| 153 | |||
| 154 | heading.x = (float)Math.cos(Math.toRadians(mCurrentAngle)); |
||
| 155 | heading.y = -(float)Math.sin(Math.toRadians(mCurrentAngle)); |
||
| 156 | heading.normalize(); |
||
| 157 | |||
| 945 | chris | 158 | spriteInstance.param.x += MISSILE_SPEED * deltaTime * heading.x; |
| 159 | spriteInstance.param.y += MISSILE_SPEED * deltaTime * heading.y; |
||
| 160 | spriteInstance.param.angle = mCurrentAngle; |
||
| 886 | chris | 161 | break; |
| 162 | } |
||
| 947 | chris | 163 | |
| 945 | chris | 164 | getGameLogic().checkProjectileHit(this); |
| 165 | |||
| 956 | chris | 166 | /*if ((spriteInstance.param.x > (GameConsts.VIRTUAL_SCREEN_WIDTH + MISSILE_WIDTH)) || |
| 945 | chris | 167 | (spriteInstance.param.x < (-MISSILE_WIDTH)) || |
| 168 | (spriteInstance.param.y > (GameConsts.VIRTUAL_SCREEN_HEIGHT+ MISSILE_HEIGHT)) || |
||
| 956 | chris | 169 | (spriteInstance.param.y < (-MISSILE_HEIGHT)))*/ |
| 170 | if (getGameLogic().isOutOfScreen(spriteInstance.param)) |
||
| 886 | chris | 171 | { |
| 172 | // out of screen -> make un alive |
||
| 945 | chris | 173 | setAlive(false); |
| 886 | chris | 174 | } |
| 175 | } |
||
| 176 | |||
| 177 | public void render() |
||
| 178 | { |
||
| 887 | chris | 179 | float t = (lifeTime % MISSILE_ROTATION_DURATION) / MISSILE_ROTATION_DURATION; |
| 180 | int frame = MathUtil.clamp((int)(t * NUM_MISSILE_FRAMES), 0, NUM_MISSILE_FRAMES-1); |
||
| 945 | chris | 181 | spriteInstance.renderFrame(frame); |
| 947 | chris | 182 | |
| 887 | chris | 183 | float rocketPulse = MathUtil.sin(lifeTime * 2000.0f) * 0.3f; |
| 184 | |||
| 890 | chris | 185 | if (mPhase == MissilePhase.PHASE_HOAMING) |
| 186 | { |
||
| 945 | chris | 187 | mMissileFrames[ROCKET_FIRE_FRAME].param.x = spriteInstance.param.x; |
| 188 | mMissileFrames[ROCKET_FIRE_FRAME].param.y = spriteInstance.param.y; |
||
| 899 | chris | 189 | mMissileFrames[ROCKET_FIRE_FRAME].param.w = ROCKET_FIRE_SIZE + ROCKET_FIRE_SIZE_VARIANCE * rocketPulse; |
| 190 | mMissileFrames[ROCKET_FIRE_FRAME].param.h = ROCKET_FIRE_SIZE; |
||
| 191 | mMissileFrames[ROCKET_FIRE_FRAME].param.pivotX = MISSILE_WIDTH + mMissileFrames[ROCKET_FIRE_FRAME].param.w - ROCKET_FIRE_OFFSET; |
||
| 192 | mMissileFrames[ROCKET_FIRE_FRAME].param.pivotY = mMissileFrames[ROCKET_FIRE_FRAME].param.h/2; |
||
| 193 | mMissileFrames[ROCKET_FIRE_FRAME].param.angle = mCurrentAngle; |
||
| 890 | chris | 194 | mMissileFrames[ROCKET_FIRE_FRAME].render(); |
| 195 | } |
||
| 886 | chris | 196 | } |
| 945 | chris | 197 | |
| 198 | @Override |
||
| 993 | chris | 199 | public void processHit(ICollidable hitObject) |
| 945 | chris | 200 | { |
| 201 | // spawn impact effect |
||
| 993 | chris | 202 | hitObject.hit(getDamage()); |
| 945 | chris | 203 | setAlive(false); |
| 204 | } |
||
| 205 | |||
| 206 | @Override |
||
| 207 | public Shape getShape() |
||
| 208 | { |
||
| 209 | return spriteInstance.getShape(); |
||
| 210 | } |
||
| 211 | |||
| 212 | @Override |
||
| 213 | public Matrix4 getShapeTransform() |
||
| 214 | { |
||
| 215 | return spriteInstance.param.getTransform(); |
||
| 216 | } |
||
| 950 | chris | 217 | |
| 218 | @Override |
||
| 219 | public AABoundingBox getBounds() |
||
| 220 | { |
||
| 221 | return spriteInstance.param.getBoundingBox(); |
||
| 222 | } |
||
| 886 | chris | 223 | } |
| 224 | |||
| 225 | |||
| 226 | // Fields=========================================================================================== |
||
| 227 | |||
| 228 | private Missile mMissiles[] = new Missile[MAX_MISSILES]; |
||
| 229 | |||
| 230 | private AtlasSprite mMissileSprite = null; |
||
| 915 | chris | 231 | private AtlasSpriteFrame mMissileFrames[] = null; |
| 890 | chris | 232 | |
| 945 | chris | 233 | private Shape mMissileShape = null; |
| 234 | |||
| 890 | chris | 235 | private Sound mRocketFireSfx = null; |
| 886 | chris | 236 | |
| 237 | // Methods========================================================================================== |
||
| 238 | |||
| 239 | public PowerUpMissile(GameLogic gameLogic) |
||
| 240 | { |
||
| 241 | super(gameLogic); |
||
| 242 | mMissileSprite = new AtlasSprite(getGraphics(), "data/textures/missile.png", "data/textures/missile.txt"); |
||
| 243 | } |
||
| 244 | |||
| 245 | @Override |
||
| 246 | public void initAsync() |
||
| 247 | { |
||
| 248 | mMissileSprite.initAsync(); |
||
| 249 | } |
||
| 250 | |||
| 251 | @Override |
||
| 252 | public void init() |
||
| 253 | { |
||
| 945 | chris | 254 | mMissileShape = ShapeUtil.createShapeFromFile("data/textures/missile.shape"); |
| 255 | |||
| 890 | chris | 256 | mRocketFireSfx = getAudio().newManagedSound("data/sounds/fire_rocket.wav"); |
| 257 | |||
| 886 | chris | 258 | mMissileSprite.init(); |
| 259 | mMissileFrames = mMissileSprite.createSpriteInstances(); |
||
| 260 | |||
| 261 | for (int i = 0; i < MAX_MISSILES; i++) |
||
| 262 | { |
||
| 263 | mMissiles[i] = new Missile(i); |
||
| 264 | } |
||
| 265 | } |
||
| 266 | |||
| 267 | @Override |
||
| 268 | public void exit() |
||
| 269 | { |
||
| 270 | mMissileFrames = null; |
||
| 271 | |||
| 272 | if (mMissileSprite != null) |
||
| 273 | { |
||
| 274 | mMissileSprite.dispose(); |
||
| 275 | mMissileSprite = null; |
||
| 276 | } |
||
| 890 | chris | 277 | |
| 278 | if (mRocketFireSfx != null) |
||
| 279 | { |
||
| 280 | getAudio().removeManagedSound(mRocketFireSfx); |
||
| 281 | mRocketFireSfx = null; |
||
| 282 | } |
||
| 886 | chris | 283 | } |
| 284 | |||
| 285 | @Override |
||
| 286 | public void update(float deltaTime) |
||
| 287 | { |
||
| 288 | int i = 0; |
||
| 289 | while (i < MAX_MISSILES) |
||
| 290 | { |
||
| 945 | chris | 291 | if (mMissiles[i].isAlive()) |
| 886 | chris | 292 | mMissiles[i].update(deltaTime); |
| 293 | i++; |
||
| 294 | } |
||
| 295 | |||
| 296 | } |
||
| 297 | |||
| 298 | @Override |
||
| 299 | public void render() |
||
| 300 | { |
||
| 301 | int i = 0; |
||
| 302 | while (i < MAX_MISSILES) |
||
| 303 | { |
||
| 945 | chris | 304 | if (mMissiles[i].isAlive()) |
| 886 | chris | 305 | mMissiles[i].render(); |
| 306 | i++; |
||
| 307 | } |
||
| 308 | } |
||
| 309 | |||
| 310 | public void launch(float x, float y) |
||
| 311 | { |
||
| 312 | // launch one upper, one lower |
||
| 313 | |||
| 314 | for (int i = 0; i < MAX_MISSILES; i++) |
||
| 315 | { |
||
| 945 | chris | 316 | if (!mMissiles[i].isAlive()) |
| 886 | chris | 317 | { |
| 318 | mMissiles[i].launch(x, y); |
||
| 319 | } |
||
| 320 | } |
||
| 321 | } |
||
| 322 | |||
| 323 | // Getters/Setters================================================================================== |
||
| 324 | |||
| 325 | } |
||
| 326 | |||
| 327 |