/*
* CheetahFighter.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.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Pina3D.Particles;
using tAC_Engine;
namespace Astropolis
{
///
/// This class represents the player's ship in the meteor madness game.
/// It can move according the rules of meteor madness, and also informs MM where to draw the ship and where to draw its projectiles
///
class CheetahFighter : Entity
{
private double mArcPosition; // Degrees of a circle corresponding to the player's ship's position
private double mArcVelocity; // Speed at which the ship can change its arcposition
private List mWeaponOffsets; // Distance from the center of the image to each firing point (in relation to width and height)
private int mFireNext; // An index of which of the 4 weapon locations to fire next
private float mRoll; // Visually roll the ship as it turns
private float mRollVelocity; // Speed at which the ship rolls
private float mRollMax; // Max amount to roll the ship
private Emitter mEngineFlare; // The particle effects for the ships's engine
private Emitter mEngineLerpFlare; // ''
private Emitter mEngineTrail; // ''
private Emitter mRepulsion; // ''
private Emitter mShieldEmitter; // Displays shields
private Vector2 mEngineOffset; // Offset to draw the flare
private Vector3 mSpace3DSize; // Size of this entity in space3D coordinates
///
/// Constructor
///
/// Ship's texture
/// In Space3D units
/// In Space3D units
/// In Space 3D units
/// In Space 3D units
public CheetahFighter(Texture2D sprite, float width, float height, float depth, float zPosition)
: base(sprite)
{
mSpace3DSize = new Vector3(width, height, depth);
mArcPosition = Math.PI/2;
mArcVelocity = Math.PI / 960;
mSize.Z = depth;
mPos.Z = depth;
mFireNext = 0;
mRollMax = (float)(Math.PI * 2.5 / 4.0);
mRollVelocity = 20f;
mRoll = 0f;
mWeaponOffsets = new List();
mWeaponOffsets.Add(new Vector2(.5f, -.8f));
mWeaponOffsets.Add(new Vector2(-.9f, .1f));
mWeaponOffsets.Add(new Vector2(.9f, .1f));
mWeaponOffsets.Add(new Vector2(-.5f, -.8f));
mEngineOffset = new Vector2(0f, 100f * mSpace3DSize.Y);
mEngineFlare = Sparx.LoadParticleEffect(@"Content\Particle Effects\EngineFlare.spx");
mEngineLerpFlare = Sparx.LoadParticleEffect(@"Content\Particle Effects\EngineFlare.spx");
mEngineTrail = Sparx.LoadParticleEffect(@"Content\Particle Effects\EngineTrail.spx");
mShieldEmitter = Sparx.LoadParticleEffect(@"Content\Particle Effects\Shield.spx");
mEngineFlare.Position3D = new Vector3(0f, 20f, .00011f);
mEngineLerpFlare.Position3D = new Vector3(0f, 10f, .00011f);
mEngineTrail.Position3D = new Vector3(0f, 0f, .0001f);
mRepulsion = new Emitter(
"Repulxzor",
new Vector3(GenericBaseApplication.GameManager.ScreenWidth / 2, GenericBaseApplication.GameManager.ScreenHeight / 2, mEngineTrail.Position3D.Z),
Vector3.Zero,
Vector3.Zero,
0f,
0f,
true,
1f,
1f);
((Gravitational)mEngineTrail.EmissionForces[0]).Center = mRepulsion;
Sparx.AddEmitter(mEngineFlare);
mEngineLerpFlare.RegularEmissionType.Modifiers[0].InitialOpacity = 0.3f;
mEngineLerpFlare.RegularEmissionType.Modifiers[0].InitialTint = Color.Blue;
mEngineLerpFlare.RegularEmissionType.Modifiers[0].FinalTint = Color.Azure;
mEngineLerpFlare.RegularEmissionType.Modifiers[0].InitialScale *= .5f;
mEngineLerpFlare.RegularEmissionType.Modifiers[0].FinalScale *= .5f;
mEngineLerpFlare.Active = false;
Sparx.AddEmitter(mEngineLerpFlare);
Sparx.AddEmitter(mEngineTrail);
UpdatePosition();
}
public double ArcPosition { set { mArcPosition = value; } get { return mArcPosition; } }
public double ArcVelocity { set { mArcVelocity = value; } get { return mArcVelocity; } }
public bool EngineFlare { set { mEngineFlare.Active = value; mEngineTrail.Active = value; } get { return mEngineFlare.Active || mEngineTrail.Active; } }
public float EngineScale { set { mEngineFlare.RegularEmissionType.Modifiers[0].FinalScale = value; } }
public override float Width { set { mSpace3DSize.X = value; } get { return mSpace3DSize.X; } }
public override float Height { set { mSpace3DSize.Y = value; } get { return mSpace3DSize.Y; } }
public override float Depth { set { mSpace3DSize.Z = value; } get { return mSpace3DSize.Z; } }
public override Vector3 Size { get { return mSpace3DSize; } }
///
/// Returns the x and y screen location of the next spawn point for a projectile
///
///
public Vector2 GetNextFiringLocation()
{
// Get the offset based on width, and then rotate it with the ship
float retX, retY, offX, offY;
offX = mWeaponOffsets[mFireNext].X * mSpace3DSize.X;
offY = mWeaponOffsets[mFireNext].Y * mSpace3DSize.Y;
retX = mPos.X + (float)Math.Cos(mRot) * offX - (float)Math.Sin(mRot) * offY;
retY = mPos.Y + (float)Math.Sin(mRot) * offX + (float)Math.Cos(mRot) * offY;
mFireNext++;
if (mFireNext >= mWeaponOffsets.Count)
mFireNext=0;
return new Vector2(retX, retY);
}
///
/// Moves the ship clockwise on the circle that it is allowed to move on
///
public void MoveRight(float dt)
{
mArcPosition -= mArcVelocity * dt * 1000;
mRoll += mRollVelocity * dt;
if (mRoll > mRollMax)
mRoll = mRollMax;
}
///
/// Moves the ship counterclockwise on the circle
///
public void MoveLeft(float dt)
{
mArcPosition += mArcVelocity * dt * 1000;
mRoll -= mRollVelocity * dt;
if (mRoll < -mRollMax)
mRoll = -mRollMax;
}
///
/// Removes the engine flare from the particle engine
///
public void KillEngineFlare()
{
mEngineFlare.Alive = false;
mEngineTrail.Alive = false;
}
///
/// Displays the appropriate particle effects
///
public void GetHit()
{
// Indicate the strength of the remaining shields through color and opacity of a particle effect
float percentLeft = AstroBaseApplication.GameManager.DotShields;
if (percentLeft >= 0)
{
mShieldEmitter.Alive = false;
mShieldEmitter = Sparx.LoadParticleEffect(@"Content\Particle Effects\Shield.spx");
mShieldEmitter.RenderScale = 0f; // Gets fixed in UpdatePosition()
// Redden the shields to indicate that they are low
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);
}
}
///
/// Tints the engine flares to signify warp drive is initiating
///
public void ColorizeEngineFlareForWarp()
{
mEngineFlare.RegularEmissionType.Modifiers[0].InitialTint = Color.WhiteSmoke;
mEngineFlare.RegularEmissionType.Modifiers[0].FinalTint = Color.DarkViolet;
}
///
/// Moves to the given arc position over the specified interval
///
public void Lerp(float newArcPosition, float duration)
{
mArcPosition = newArcPosition;
// Get the new position based its angle on the circle
Vector2 PositionFromOrigin = new Vector2((float)Math.Cos(mArcPosition), (float)Math.Sin(mArcPosition));
// Move the ship away from the edge of the screen for aesthetics
Vector3 newPos = new Vector3(
newPos.X = .8F * PositionFromOrigin.X,
newPos.Y = .8F * PositionFromOrigin.Y,
mPos.Z);
Lerp(newPos, mSize, (float)(mRot - mRoll), duration);
}
///
/// Updates the inherited Position properties based on the arcposition
///
private void UpdatePosition()
{
// Find the screen position to draw the engine effects
Rectangle proj = Space3D.Project(mPos.X, mPos.Y, mPos.Z, mSpace3DSize.X, mSpace3DSize.Y, -1f);
float rotX = proj.X + (float)Math.Cos(mRot) * mEngineOffset.X - (float)Math.Sin(mRot) * mEngineOffset.Y;
float rotY = proj.Y + (float)Math.Sin(mRot) * mEngineOffset.X + (float)Math.Cos(mRot) * mEngineOffset.Y;
float scale = .1f / mPos.Z;
mEngineFlare.RenderRotation = (float)mRot;
mEngineFlare.RenderScale = scale;
mEngineFlare.Transform = Matrix.CreateScale(scale) * Matrix.CreateRotationZ((float)mRot) * Matrix.CreateTranslation(proj.X, proj.Y, 0f);
mEngineLerpFlare.RenderRotation = mEngineFlare.RenderRotation;
mEngineLerpFlare.RenderScale = scale;
mEngineLerpFlare.Transform = mEngineFlare.Transform;
mEngineTrail.Position2D = new Vector2(proj.X, proj.Y);
if (!IsLerping)
{
// Get its position based its angle on the circle
Vector2 PositionFromOrigin = new Vector2((float)Math.Cos(mArcPosition), (float)Math.Sin(mArcPosition));
// Move the ship away from the edge of the screen for aesthetics
mPos.X = .8F * PositionFromOrigin.X;
mPos.Y = .8F * PositionFromOrigin.Y;
// Cleanup variables
mArcPosition %= Math.PI * 2;
mRot = mArcPosition - Math.PI / 2;
mRot += mRoll;
mEngineLerpFlare.Active = false;
mShieldEmitter.RenderScale = 2f;
mShieldEmitter.Transform = Matrix.CreateScale(2f) * Matrix.CreateTranslation(proj.X, proj.Y, 0f);
}
else
{
mEngineLerpFlare.Active = true;
}
}
///
/// Updates game logic
///
public override void Update()
{
float dT = GenericBaseApplication.GameManager.ElapsedSeconds;
// Return roll to neutral
if (mRoll > 0)
mRoll -= mRollVelocity * dT / 2f;
else if (mRoll < 0)
mRoll += mRollVelocity * dT / 2f;
if (Math.Abs(mRoll) < mRollVelocity * dT / 2f)
mRoll = 0f;
UpdatePosition();
if (mVisible == false)
mEngineFlare.RegularEmissionType.Modifiers[0].InitialOpacity = 0f;
else
mEngineFlare.RegularEmissionType.Modifiers[0].InitialOpacity = Opacity;
base.Update();
}
}
}