/* * 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(); } } }