/* * SpacePirate.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 enemy ships that spawn from wormholes in meteor madness /// Space Pirates can shoot at the player /// They also explode when the player shoots them enough times or they hit enough meteors /// Upon explosion, they drop coins that can be collected by the player /// class SpacePirate : UFO { 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 float mCooldownTime; // The minimum base time between shots private float mCooldownTimer; // Counts down until the next shot public double ArcPosition { set { mArcPosition = value; UpdatePosition(); } get { return mArcPosition; } } public double ArcVelocity { set { mArcVelocity = value; } get { return mArcVelocity; } } /// /// Constructor /// /// Image to use /// In Space3D units /// In Space3D units /// In Space3D units /// Damage this ship can take before dying /// Base time between shots, although this time is reduced at later levels public SpacePirate(Texture2D texture, float width, float height, float depth, int hitPoints, float shotCooldown) : base(texture, width, height, depth, hitPoints) { mArcVelocity = Math.PI / 1920; mCooldownTimer = (3 + (shotCooldown * 2)) * GenericBaseApplication.GameManager.RandomNumber(.90f, 1.10f); // Wait for the player to react before opening fire mCooldownTime = shotCooldown; } /// /// Deals the specified amount of damage to the space priate, potentially killing it /// /// public override void GetHit(int damage) { mHitPoints -= damage; if (mHitPoints <= 0) Destroy(); else { if (mPos.Z > -1) { // 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)(mHitPoints / 100f); 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); } } } /// /// Spawns the appropriate particle effects and/or entities /// public override void Destroy() { mAlive = false; Emitter splosion = Sparx.LoadParticleEffect(@"Content\Particle Effects\MediumExplosion.spx"); Rectangle proj = Space3D.Project(this.X, this.Y, this.Z, this.Width, this.Height, -1f); float scaling = proj.Width * .01f; splosion.RenderScale = scaling; splosion.Transform = Matrix.CreateScale(scaling) * Matrix.CreateTranslation(proj.X, proj.Y, MathHelper.Clamp(this.Z / 5f, 0f, 1f)); Sparx.AddEmitter(splosion); splosion = Sparx.LoadParticleEffect(@"Content\Particle Effects\MediumExplosion.spx"); scaling *= .5f; splosion.RenderScale = scaling; splosion.Transform = Matrix.CreateScale(scaling) * Matrix.CreateTranslation(proj.X, proj.Y, MathHelper.Clamp(this.Z / 5f, 0f, 1f)); Sparx.AddEmitter(splosion); } /// /// Damages player /// public override void CollideWithPlayer(Entity player) { ((MeteorMadness)AstroBaseApplication.MiniGame).ShooterShieldHit(50); Destroy(); } /// /// Implements basic AI /// /// True if the AI should fire, false if it should not public override bool React(CheetahFighter playerShip) { float dt = AstroBaseApplication.GameManager.ElapsedMilliseconds; mCooldownTimer -= dt / 1000; if (playerShip == null) return false; if (Math.Abs(mArcPosition - playerShip.ArcPosition) > .01) { if (mArcPosition < playerShip.ArcPosition) MoveLeft(dt); else MoveRight(dt); } // Fire if the space pirate is lined up with the player if (Collides2D(this, playerShip) && mCooldownTimer < 0) { Fire(); return true; } return false; } /// /// Moves the space pirate clockwise along the circumference of the Space3D cylinder /// /// Seconds since last update private void MoveLeft(float dt) { mArcPosition += mArcVelocity * dt; UpdatePosition(); } /// /// Moves the space pirate counterclockwise along the circumference of the Space3D cylinder /// /// Seconds since last update private void MoveRight(float dt) { mArcPosition -= mArcVelocity * dt; UpdatePosition(); } /// /// Reset the firing cooldown /// private void Fire() { mCooldownTimer = mCooldownTime; } /// /// Updates the inherited Position properties based on the arcposition /// private void UpdatePosition() { Vector2 PositionFromOrigin = new Vector2((float)Math.Cos(mArcPosition), (float)Math.Sin(mArcPosition)); mArcPosition %= Math.PI * 2; mPos.X = .8F * PositionFromOrigin.X; mPos.Y = .8F * PositionFromOrigin.Y; mRot = mArcPosition - Math.PI / 2; } public override void Update() { base.Update(); Rectangle proj = Space3D.Project(this.X, this.Y, this.Z, this.Width, this.Height, -1f); float scaling = proj.Width * .015f; mShieldEmitter.RenderScale = scaling; mShieldEmitter.Transform = Matrix.CreateScale(scaling) * Matrix.CreateTranslation(proj.X, proj.Y, MathHelper.Clamp(this.Z / 5f, 0f, 1f)); } } }