/*
* Boss.cs
* Authors: August Zinsser
*
* Copyright Matthew Belmonte 2007
*/
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Pina3D.Particles;
using tAC_Engine;
namespace Astropolis
{
///
/// The version of the photon torpedo that the boss fires
///
class BossLaser : PhotonTorpedo
{
///
/// Create a new boss projectile
///
///
///
public BossLaser(Vector3 spawnLocation, float spawnDepth, float killDepth)
: base(true, Color.DarkSalmon, 0, spawnLocation, .5f, .5f, .5f, -15f, spawnDepth, killDepth)
{
mPos.Z = spawnDepth;
mFriendly = false;
mDamage = 25;
}
///
/// Scroll the torpedoes
///
public override void Update()
{
base.Update();
// Update the photon's position
if (mIsGoingAway && mPos.Z > mKillDepth ||
!mIsGoingAway && mPos.Z < mKillDepth)
mAlive = false;
// Adjust the Particles
Rectangle proj = Space3D.Project(mPos.X, mPos.Y, mPos.Z, mSpace3DSize.X, mSpace3DSize.Y, -1f);
float zDepth = mPos.Z / mSpawnDepth;
if (mIsGoingAway)
zDepth = mPos.Z / mKillDepth;
float scale = 1;
mTrailEmitter.Position3D = new Vector3(proj.X, proj.Y, MathHelper.Clamp(zDepth, 0f, 1f));
mTrailEmitter.SpawnRate = (Math.Max(zDepth, .1f)) * .1f;
mHeadEmitter.RenderScale = scale * 2;
mHeadEmitter.Transform = Matrix.CreateScale(scale) * Matrix.CreateTranslation(proj.X, proj.Y, MathHelper.Clamp(1 - scale, 0f, 1f));
if (mIsGoingAway)
{
mTrailEmitter.RegularEmissionType.Modifiers[0].InitialOpacity = scale;
mTrailEmitter.RegularEmissionType.Modifiers[0].FinalOpacity = scale;
mHeadEmitter.RegularEmissionType.Modifiers[0].InitialOpacity = scale;
}
// Kill the particle effect if the torpedo dies
if (!mAlive)
{
mTrailEmitter.Alive = false;
mHeadEmitter.Alive = false;
}
}
}
///
/// The rockets that the boss fires. This extends PhotonTorpedo for the sake of plugging into MeteorMadness without reworking how
/// projectiles work.
///
class BossRocket : PhotonTorpedo
{
public override Vector3 CollisionSize { get { return Vector3.One; } } // Return a large collision box
///
/// Create a new Rocket
///
///
///
///
public BossRocket(Vector3 spawnLocation, float rotation, float spawnDepth, float killDepth)
: base(true, Color.Gray, 0, spawnLocation, .125f, .125f, 1f, -5f, spawnDepth, killDepth)
{
mRot = rotation;
mPos.Z = spawnDepth;
mFriendly = false;
mDamage = 15;
mHeadEmitter.KillAllEmissions();
Sparx.RemoveEmitter(mHeadEmitter);
Texture2D rocketTexture = TextureManager.Load(@"Content\MiniGames\MMRocket");
mSprite = new Animation(new Vector2(rocketTexture.Width, rocketTexture.Height));
mSprite.AddClip("Rocket", rocketTexture, 1, 0f);
mSprite.Play("Rocket");
Sparx.RemoveEmitter(mTrailEmitter);
mTrailEmitter = Sparx.LoadParticleEffect(@"Content\Particle Effects\SmokeTrail.spx");
Rectangle proj = Space3D.Project(mPos.X, mPos.Y, mPos.Z, mSpace3DSize.X, mSpace3DSize.Y, -1f);
mTrailEmitter.Position3D = new Vector3(proj.X, proj.Y, -mPos.Z / killDepth);
Sparx.AddEmitter(mTrailEmitter);
}
///
/// Scroll the torpedoes
///
public override void Update()
{
base.Update();
mVel.Z *= 1.01f;
float zDepth = mPos.Z / mSpawnDepth;
float scale = 1 - zDepth;
mTrailEmitter.SpawnRate = (Math.Max( (float)Math.Pow(zDepth, 1.2f), 0f)) * .5f;
mTrailEmitter.RegularEmissionType.Modifiers[0].FinalScale += scale * .5f;
mTrailEmitter.MaxSpawnRadius += scale;
}
}
///
/// The rocket pods on the outside of the boss's missile ring
///
public class RocketPod
{
public int HitPoints;
public Entity Entity;
public Vector3 Offset;
public float BeginRotation;
public float EndRotation;
public void GetHit(int damage, Vector3 hitFromPosition)
{
HitPoints -= damage;
// Display the damage
Rectangle proj = Space3D.Project(this.Entity.Position.X, this.Entity.Position.Y, hitFromPosition.Z, 1f, 1f, -1f);
float scale = proj.Width * .005f;
if (HitPoints <= 0)
scale *= 5.0f;
Emitter splosion = Sparx.LoadParticleEffect(@"Content\Particle Effects\SmallExplosion.spx");
splosion.Transform = Matrix.CreateScale(scale) * Matrix.CreateTranslation(proj.X, proj.Y, 0f);
splosion.RenderScale = scale;
Sparx.AddEmitter(splosion);
}
}
///
/// This represents the boss in Meteor Madness.
/// It maintains an internal state machine and gets a handle to the meteor madness game on update in order to spawn attacks.
///
class Boss : UFO
{
public enum States { Approach, Idle, Boost, UnBoost, Turning, FarAttack, NearAttack, Dying };
protected MeteorMadness mGame; // Handle to the meteor madness game
protected List mDebris; // Parts of the ship that fly off
protected States mState; // State machine for AI logic
protected float mStateTimer; // Some states are timed
protected int mShields; // Must be destroyed before any other damage can occur
protected int mMaxShields; // ''
protected int mMaxHitPoints; // Used to calculate life percentage
protected float mIdleZ; // Z-Depth of the ship in that state
protected float mBoostZ; // '' (actually, the z-Depth to start decelerating but that doesn't really matter)
protected float mShieldedDepth; // The boss actually gets smaller after its shields are gone
protected List mRocketPods; // Each rocket pod on the ring
protected bool mRingGone; // If the ring is still attached
protected bool mNeedsToTurn; // True when the boss needs to turn around
protected float mTurningTimer; // Counts down as the ship is turning around
protected bool mVulnerable; // Whether the ship can be hit
protected float mDeathTimer; // Counts down to from the player "killing" the boss to the game recognizing the boss is dead
protected Vector3 mShake; // Shake when dying
protected Emitter mDyingExplosions; // Emits death explosions
protected Emitter[] mEngineFlares; // Engine flames
protected Emitter mFlashEmitter; // MuzzleFlare
protected Vector2[] mEngineFlareOffsets; // ''
protected float mShotTimer; // Counts down to shooting
protected int mLastRocket; // The last rocket that was fired
protected Queue mNearAttackDelays; // Time between each near attack shot
protected Queue mFarAttackDelays; // Time between each far attack
protected bool mWaitingForDialog; // Wait until the user has read the encounter dialog to begin attacking
public float ShieldLife { get { return (float)mShields / (float)mMaxShields; } }
public float RocketPodLife { get { return (float)mRocketPods.Count / 24f; } }
public float HullLife { get { return (float)mHitPoints / (float)mMaxHitPoints; } }
///
/// Constructor
///
/// In Space3D units
/// In Space3D units
/// In Space3D units
/// How many hitpoints before the ship is destroyed. This does not include shields.
/// How much damage the shields can take before the main body can be damaged
public Boss(MeteorMadness game, float width, float height, float depth, float idleZ, float boostZ, int shields, int hitPoints)
: base(null, width, height, depth, hitPoints)
{
mGame = game;
mSpace3DSize = new Vector3(width, height, depth);
mShieldedDepth = depth;
mIdleZ = idleZ;
mPos.Z = boostZ * 10f;
mBoostZ = boostZ;
mMaxShields = shields;
mMaxHitPoints = hitPoints;
mShields = shields;
mShake = Vector3.Zero;
mAngVel = 0f;
mWaitingForDialog = true;
Texture2D bossSpriteSheet = TextureManager.Load(@"Content\MiniGames\MMBossSpriteSheet");
mSprite = new Animation(new Vector2(bossSpriteSheet.Width / 2, bossSpriteSheet.Height / 2));
mSprite.AddClip("Phase1", bossSpriteSheet, 1, 0, 0);
mSprite.AddClip("Phase2", bossSpriteSheet, 1, 1, 0);
mSprite.AddClip("Phase3", bossSpriteSheet, 1, 2, 0);
mSprite.Play("Phase1");
mDebris = new List();
Texture2D ringSpriteSheet = TextureManager.Load(@"Content\MiniGames\MMBossDebris");
Animation debrisAnim = new Animation(new Vector2(ringSpriteSheet.Width / 2, ringSpriteSheet.Height / 2));
debrisAnim.AddClip("Piece1", ringSpriteSheet, 1, 0, 0);
mDebris.Add(new Entity(debrisAnim, this.Position, this.Size));
debrisAnim = new Animation(new Vector2(ringSpriteSheet.Width / 2, ringSpriteSheet.Height / 2));
debrisAnim.AddClip("Piece2", ringSpriteSheet, 1, 1, 0);
mDebris.Add(new Entity(debrisAnim, this.Position, this.Size));
debrisAnim = new Animation(new Vector2(ringSpriteSheet.Width / 2, ringSpriteSheet.Height / 2));
debrisAnim.AddClip("Piece3", ringSpriteSheet, 1, 2, 0);
mDebris.Add(new Entity(debrisAnim, this.Position, this.Size));
debrisAnim = new Animation(new Vector2(ringSpriteSheet.Width / 2, ringSpriteSheet.Height / 2));
debrisAnim.AddClip("Piece4", ringSpriteSheet, 1, 3, 0);
mDebris.Add(new Entity(debrisAnim, this.Position, this.Size));
for(int i = 0; i < mDebris.Count; i++)
mDebris[i].Visible = false;
Texture2D[] rocketPods = new Texture2D[3];
rocketPods[0] = TextureManager.Load(@"Content\MiniGames\RocketPodA");
rocketPods[1] = TextureManager.Load(@"Content\MiniGames\RocketPodB");
rocketPods[2] = TextureManager.Load(@"Content\MiniGames\RocketPodC");
int numPods = 24;
float rotationOffset = (float)(Math.PI * 2.0 / numPods * 0.5);
mRocketPods = new List();
for (int i = 0; i < numPods; i++)
{
float thisArcRotation = (float)((float)i * Math.PI * 2.0 / (float)numPods);
Vector3 thisPositionOffset = new Vector3((float)Math.Cos(thisArcRotation), (float)Math.Sin(thisArcRotation), 0f);
// Hardcode adjust values so they end up in the right place
thisPositionOffset.X = thisPositionOffset.X * 1.15f;
thisPositionOffset.Y = thisPositionOffset.Y * 1.3f + 0f;
thisPositionOffset.Z = thisPositionOffset.Y * .1f;
RocketPod newPod = new RocketPod();
newPod.Entity = new Entity(rocketPods[i % 3]);
newPod.Entity.Position = mPos + thisPositionOffset;
newPod.Offset = thisPositionOffset;
float rocketWidth = .064f * mSpace3DSize.X;
float rocketHeight = rocketWidth * newPod.Entity.Height / newPod.Entity.Width;
newPod.Entity.Size = new Vector3(rocketWidth, rocketHeight, rocketHeight);
game.GameBoard.AddEntity(newPod.Entity);
newPod.HitPoints = 30;
newPod.BeginRotation = thisArcRotation - rotationOffset;
newPod.EndRotation = thisArcRotation + rotationOffset;
mRocketPods.Add(newPod);
}
mFlashEmitter = Sparx.LoadParticleEffect(@"Content\Particle Effects\Flash.spx");
mFlashEmitter.RenderScale = .3f;
mEngineFlares = new Emitter[3];
mEngineFlares[0] = Sparx.LoadParticleEffect(@"Content\Particle Effects\EngineFlare.spx");
mEngineFlares[1] = Sparx.LoadParticleEffect(@"Content\Particle Effects\EngineFlare.spx");
mEngineFlares[2] = Sparx.LoadParticleEffect(@"Content\Particle Effects\EngineFlare.spx");
((Particle)(mEngineFlares[0].RegularEmissionType)).Height *= .5f;
((Particle)(mEngineFlares[1].RegularEmissionType)).Height *= .5f;
((Particle)(mEngineFlares[2].RegularEmissionType)).Height *= .5f;
mEngineFlares[0].RenderScale = 0f;
mEngineFlares[1].RenderScale = 0f;
mEngineFlares[2].RenderScale = 0f;
mEngineFlareOffsets = new Vector2[3];
mEngineFlareOffsets[0] = new Vector2(0f, -5f);
mEngineFlareOffsets[1] = new Vector2(-35f, 15f);
mEngineFlareOffsets[2] = new Vector2(30f, 15f);
Sparx.AddEmitter(mEngineFlares[0]);
Sparx.AddEmitter(mEngineFlares[1]);
Sparx.AddEmitter(mEngineFlares[2]);
mDyingExplosions = Sparx.LoadParticleEffect(@"Content\Particle Effects\MediumChainExplosions.spx");
mNearAttackDelays = new Queue();
mNearAttackDelays.Enqueue(.1f);
mNearAttackDelays.Enqueue(.1f);
mNearAttackDelays.Enqueue(.5f);
mFarAttackDelays = new Queue();
for (int i = 0; i < 36; i++)
mFarAttackDelays.Enqueue(.05f);
mFarAttackDelays.Enqueue(3f);
mState = States.Approach;
mVulnerable = false;
mNeedsToTurn = false;
}
///
/// Call this to allow the boss to start fighting
///
public void Start()
{
mWaitingForDialog = false;
}
///
/// Returns a list of exposed rocketpods to test for collision
///
///
public List GetVulnerableRocketPods()
{
if (mVulnerable && mShields <= 0)
{
return mRocketPods;
}
return new List();
}
///
/// Deals the specified amount of damage to this ship, potentially killing it. The boss may only be vulnerable at certain angles,
/// so the angle at which it is hit is important.
///
///
public void GetHit(int damage, Vector3 hitFromPosition)
{
if (mState == States.Dying)
return;
// Shields must be taken down first
if (mShields > 0 && mVulnerable)
{
mShields -= damage;
// Shield particle effect
mShieldEmitter.RegularEmissionType.LifeExpectancy = .1f;
mShieldEmitter = Sparx.LoadParticleEffect(@"Content\Particle Effects\Shield.spx");
// Redden the shields to indicate that they are low
float percentLeft = (float)mShields / (float)mMaxShields;
Color newColor = new Color((byte)((255 * (1 - percentLeft))),
(byte)((150 * (percentLeft))),
(byte)((255 * (percentLeft))));
mShieldEmitter.RegularEmissionType.Modifiers[0].InitialTint = newColor;
mShieldEmitter.RegularEmissionType.Modifiers[0].InitialOpacity = percentLeft;
Sparx.AddEmitter(mShieldEmitter);
}
else if (mVulnerable && mRingGone)
{
if (mRocketPods.Count <= 0)
{
// Rocket pods are gone, so go ahead and damage the ship
mHitPoints -= damage;
// Display the damage
Vector2 offset = new Vector2(hitFromPosition.X, hitFromPosition.Y);
offset = Vector2.Normalize(offset);
offset = Vector2.Multiply(offset, .5f);
Rectangle proj = Space3D.Project(offset.X, offset.Y, hitFromPosition.Z, 1f, 1f, -1f);
float scale = proj.Width * .0025f;
Emitter splosion = Sparx.LoadParticleEffect(@"Content\Particle Effects\SmallExplosion.spx");
splosion.Transform = Matrix.CreateScale(.5f, 1f, 1f) * Matrix.CreateTranslation(proj.X, proj.Y, 0f);
splosion.RenderScale = scale;
Sparx.AddEmitter(splosion);
if (mHitPoints <= 0)
{
mState = States.Dying;
mDeathTimer = 5f;
FadeOut(5f);
proj = Space3D.Project(this.X, this.Y, this.Z, this.Width, this.Height, -1f);
mDyingExplosions.Position2D = new Vector2(proj.X, proj.Y);
Sparx.AddEmitter(mDyingExplosions);
}
}
}
}
///
/// Update boss logic
///
public override void Update()
{
float dT = AstroBaseApplication.GameManager.ElapsedSeconds;
mStateTimer -= dT;
mTurningTimer -= dT;
mDeathTimer -= dT;
mShotTimer -= dT;
mVulnerable = true;
if (mState == States.Approach || mState == States.UnBoost || mNeedsToTurn)
mVulnerable = false;
// Change collision size if shields are up or down
if (mShields > 0)
mSpace3DSize.Z = mShieldedDepth * .5f;
else
mSpace3DSize.Z = mShieldedDepth * .01f;
// Move the shields
Rectangle proj = Space3D.Project(this.X, this.Y, this.Z, this.Width, this.Height, -1f);
float scale = proj.Width * .009f;
mShieldEmitter.RenderScale = scale;
mShieldEmitter.Transform = Matrix.CreateScale(scale) * Matrix.CreateTranslation(proj.X, proj.Y, 0f);
// Move the engine flares
scale = proj.Width * .003f;
for (int i = 0; i < 3; i++)
{
mEngineFlares[i].RenderScale = scale;
mEngineFlares[i].Transform = Matrix.CreateScale(scale) * Matrix.CreateTranslation(proj.X + scale * mEngineFlareOffsets[i].X, proj.Y + scale * mEngineFlareOffsets[i].Y, 0f);
}
// Destroy ring if necessary
if (mRocketPods.Count == 0 && !mRingGone)
{
mRingGone = true;
mNeedsToTurn = true;
mVulnerable = false;
mSprite.Play("Phase2");
// Display the damage
scale = 5.0f;
Emitter splosion = Sparx.LoadParticleEffect(@"Content\Particle Effects\SmallExplosion.spx");
splosion.Transform = Matrix.CreateScale(scale) * Matrix.CreateTranslation(proj.X, proj.Y, 0f);
splosion.RenderScale = scale;
splosion.MinSpawnRadius = 15;
splosion.MaxSpawnRadius = 15;
splosion.DieAfter *= 10;
Sparx.AddEmitter(splosion);
mDebris[0].Play("Piece1");
mDebris[1].Play("Piece2");
mDebris[2].Play("Piece3");
mDebris[3].Play("Piece4");
mDebris[0].Position = new Vector3(-.7f, -.9f, -.0001f);
mDebris[1].Position = new Vector3( .7f, -.9f, -.0002f);
mDebris[2].Position = new Vector3(-.7f, 1.0f, -.0003f);
mDebris[3].Position = new Vector3( .7f, 1.0f, -.0004f);
for (int i = 0; i < mDebris.Count; i++)
{
mDebris[i].Size = Vector3.Multiply(this.Size, .5f);
mDebris[i].Position += this.Position;
mDebris[i].Velocity = mDebris[i].Position;
mDebris[i].dX *= GenericBaseApplication.GameManager.RandomNumber(.01f, 1.0f);
mDebris[i].dY *= GenericBaseApplication.GameManager.RandomNumber(.01f, 1.0f);
mDebris[i].dZ = GenericBaseApplication.GameManager.RandomNumber(-.5f, -.05f);
mDebris[i].Visible = true;
mDebris[i].FadeOut(4f);
mGame.GameBoard.AddEntity(mDebris[i]);
}
}
for (int i = mDebris.Count - 1; i >= 0; i--)
{
mDebris[i].Update();
mDebris[i].Velocity *= 1.02f;
if (mDebris[i].Z < mGame.GameBoard.MinZ)
mDebris.RemoveAt(i);
}
// Perform logic based on state
switch (mState)
{
case States.Approach:
// The initial state
if (mPos.Z > mIdleZ)
{
float distanceLeft = mPos.Z / mIdleZ;
mPos.Z -= distanceLeft * .03f + .01f;
}
if (mPos.Z < mIdleZ)
mPos.Z = mIdleZ;
// GOTO: idle
if (mPos.Z == mIdleZ)
{
mState = States.Idle;
mStateTimer = 10f;
}
break;
case States.Idle:
// Sit there and let the player hit the boss (or wait for the player to finish reading dialog)
if (mStateTimer < 0 && !mWaitingForDialog)
{
mState = States.Boost;
mStateTimer = GenericBaseApplication.GameManager.RandomNumber(3f, 6f);
}
// GOTO: boost, close attack
break;
case States.Boost:
// Speed away from the player
if (mPos.Z < mBoostZ)
{
// Speed up
mVel.Z += .1f;
for (int i = 0; i < 3; i++)
mEngineFlares[i].RenderScale *= 2.5f;
}
else
{
// Slow down
if (mVel.Z > 0)
mVel.Z *= .5f;
if (mVel.Z < .1f)
mVel.Z = 0;
for (int i = 0; i < 3; i++)
mEngineFlares[i].RenderScale *= 1.5f;
}
// GOTO: Far attack, Turn around
if (mStateTimer < 0)
{
if (mNeedsToTurn)
{
mTurningTimer = 1f;
FadeOut(1f);
mNeedsToTurn = false;
mState = States.Turning;
mEngineFlares[0].Alive = false;
mEngineFlares[1].Alive = false;
mEngineFlares[2].Alive = false;
}
else
{
mStateTimer = GenericBaseApplication.GameManager.RandomNumber(6f, 12f);
mState = States.FarAttack;
}
}
break;
case States.FarAttack:
// Attack the player with rockets
if (mShotTimer < 0 && mStateTimer > 2f)
{
if (mLastRocket >= mRocketPods.Count)
mLastRocket = 0;
RocketPod curRocket = mRocketPods[mLastRocket++];
BossRocket bossRocket = new BossRocket(
curRocket.Entity.Position,
(curRocket.BeginRotation + curRocket.EndRotation) / 2f - MathHelper.PiOver2,
this.Z,
mGame.GameBoard.MinZ);
mGame.Projectiles.Add(bossRocket);
mGame.GameBoard.AddEntity(bossRocket);
mShotTimer = mFarAttackDelays.Dequeue();
mFarAttackDelays.Enqueue(mShotTimer);
Rectangle screenCoords = Space3D.Project(bossRocket.X, bossRocket.Y, bossRocket.Z, bossRocket.Width, bossRocket.Height, 0f);
Emitter flash = (Emitter)mFlashEmitter.Clone();
flash.RenderScale = .05f;
flash.Position2D = new Vector2(screenCoords.X, screenCoords.Y);
Sparx.AddEmitter(flash);
}
for (int i = 0; i < 3; i++)
mEngineFlares[i].RenderScale *= 1.5f;
// GOTO: Unboost
if (mStateTimer < 0)
{
// Let the player catch up and then resume idle
mState = States.UnBoost;
}
break;
case States.UnBoost:
// Return from a boost to idle state
if (mPos.Z > mIdleZ)
{
mPos.Z -= 1f;
}
if (mPos.Z < mIdleZ)
mPos.Z = mIdleZ;
// GOTO: idle, near attack
if (mPos.Z == mIdleZ)
{
if (mRingGone)
{
mAngVel = (float)(Math.PI / .96);
mState = States.NearAttack;
}
else
{
mState = States.Idle;
mStateTimer = GenericBaseApplication.GameManager.RandomNumber(10f, 15f);
}
}
break;
case States.Turning:
// Turn around and face the player
// GOTO: UnBoost
if (mTurningTimer <= 0)
{
mSprite.Play("Phase3");
FadeIn(1f);
mState = States.UnBoost;
}
break;
case States.NearAttack:
// Attack the player relentlessly!
if (mTurningTimer < 0)
{
mAngVel *= -1f;
mTurningTimer = GenericBaseApplication.GameManager.RandomNumber(5f, 10f);
}
if (mShotTimer < 0)
{
mShotTimer = mNearAttackDelays.Dequeue();
mNearAttackDelays.Enqueue(mShotTimer);
Vector3 direction = new Vector3(.5f * (float)Math.Cos(mRot + MathHelper.PiOver2), .5f * (float)Math.Sin(mRot + MathHelper.PiOver2), this.Position.Z);
// Fire a 5-shot spread
for (int i = 0; i < 5; i++)
{
BossLaser shot = new BossLaser(
direction,
this.Position.Z,
mGame.GameBoard.MinZ);
shot.dX += GenericBaseApplication.GameManager.RandomNumber(-.1f, .1f);
shot.dY += GenericBaseApplication.GameManager.RandomNumber(-.1f, .1f);
shot.Z -= i * .5f;
mGame.Projectiles.Add(shot);
mGame.GameBoard.AddEntity(shot);
// Put a flash on the last shot (looks the best at taht location)
if (i == 4)
{
Rectangle screenCoords = Space3D.Project(shot.X, shot.Y, shot.Z, shot.Width, shot.Height, 0f);
Emitter flash = (Emitter)mFlashEmitter.Clone();
flash.Position2D = new Vector2(screenCoords.X, screenCoords.Y);
Sparx.AddEmitter(flash);
}
}
}
break;
case States.Dying:
// Shake, spin and die
mShake = new Vector3(
.05f * (float)Math.Cos(GenericBaseApplication.GameManager.TotalSeconds * 25f),
.01f * (float)Math.Sin(GenericBaseApplication.GameManager.TotalSeconds * 5f),
0f);
mAngVel *= 1.01f;
// GOTO: Nothing
if (mDeathTimer <= 0)
{
mDyingExplosions.Alive = false;
mAlive = false;
}
break;
}
this.Position += mShake;
base.Update();
// Update rocket pods
List deathRow = new List();
foreach (RocketPod rocketPod in mRocketPods)
{
rocketPod.Entity.Update();
rocketPod.Entity.Position = mPos + rocketPod.Offset;
if (rocketPod.HitPoints <= 0)
{
mGame.GameBoard.RemoveEntity(rocketPod.Entity);
deathRow.Add(rocketPod);
}
}
foreach (RocketPod corpse in deathRow)
mRocketPods.Remove(corpse);
}
}
}