/* * Ship.cs * Authors: Brian Chesbrough * * 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 System.Diagnostics; using Pina3D.Particles; using tAC_Engine; namespace Astropolis { /// /// Base class for Player, merchant and raider ships in Hacker havok /// class Ship : Entity { private int mHealth; // Health of ship private int mSpeed; // Amount of movement points ship has for each turn private float mMovementMeter; // Meter that gets refilled with movement points at the beginng of each turn private bool mCloaked; // true when ship's cloaking device is on private List mCargo; // Ships Cargo, where payloads are stored private float mRotateTimer; // used to control duration of rotation private float mTranslationTimer;// Used to control duration of translation private Vector2 mLookAt; // look vector private bool mArrivedAtDest; // true after the player arrives at a new destination private float mDistance; // length from the ship to its target, subtracted from movementMeter at end of translation public bool ArrivedAtDest { set { mArrivedAtDest = value; } get { return mArrivedAtDest; } } public int Speed { set { mSpeed = value; } get { return mSpeed; } } public int Health { set { mHealth = value; } get { return mHealth; } } public float MovementMeter { set { mMovementMeter = value; } get { return mMovementMeter; } } public bool Cloak { set { mCloaked = value; } get { return mCloaked; } } public List Cargo { set { mCargo = value; } get { return mCargo; } } public float TranslationTimer { get { return mTranslationTimer; } } /// /// Constructor /// /// public Ship(Texture2D Sprite) : base(Sprite) { mCargo = new List(); mTranslationTimer = 0; //initialize the look vector to up mLookAt = new Vector2(0, -1); } /// /// Causes ship to turn and point at entity /// /// Entity to look at public void lookAt(Entity targetEntity) { //calculate new look vector Vector2 newLook = new Vector2(targetEntity.Position.X - this.Position.X, targetEntity.Position.Y - this.Position.Y); //normalize that vector newLook.Normalize(); //get the dot product of straight up(0,-1) and the new look vector double dotProduct = 0 * newLook.X + -1 * newLook.Y; //calculate the rotational angle mTargetRot = Math.Acos(dotProduct); //Lots of anoying circle math going on here //basically this checks where you want to point and where you are currnetly pointing //then takes the shortest route to get there. if (newLook.X >= 0) { if (mLookAt.X < 0 && mLookAt.Y < 0) { if (newLook.Y <= 0) { mRot -= 2 * Math.PI; } } } else { double correctAngle; //if the angle was on the left then convert into radians, find correct angle, then convert back correctAngle = mTargetRot * 57.2957795; correctAngle = 360 - correctAngle; mTargetRot = correctAngle / 57.2957795; if (newLook.Y <= 0 && mLookAt.X >= 0) { mRot += 2 * Math.PI; } } //store our new look vector mLookAt.X = newLook.X; mLookAt.Y = newLook.Y; //if your rotating over a larger angle, take longer to rotate double difference = mTargetRot - mRot; if (difference < 1.6 && difference > -1.6) { mRotateTimer = .5f; } else { mRotateTimer = 1f; } } public void goTo(Entity targetEntity) { //Get position we are going to mTargetPos = targetEntity.Position; mDistance = (float)Math.Sqrt(Math.Pow((mPos.X - mTargetPos.X), 2) + Math.Pow((mPos.Y - mTargetPos.Y), 2) + Math.Pow((mPos.Z - mTargetPos.Z), 2)); mTranslationTimer = 1f; } /// /// Logic updates /// public override void Update() { float dt = GenericBaseApplication.GameManager.ElapsedSeconds; //If rotating if (mRotateTimer > 0) { //Rotate double rotationRemaining = mTargetRot - mRot; float angularVelocity = (float)rotationRemaining / mRotateTimer; mRot += angularVelocity * dt; mRotateTimer -= dt; //ensure we point at the target if (mRotateTimer < 0) { mRot = mTargetRot; } } else if (mTranslationTimer > 0) { float distanceRemaining = (float)Math.Sqrt(Math.Pow((mPos.X - mTargetPos.X), 2) + Math.Pow((mPos.Y - mTargetPos.Y), 2) + Math.Pow((mPos.Z - mTargetPos.Z), 2)); float speed = distanceRemaining / mTranslationTimer; Vector3 direction = mTargetPos - mPos; direction.Normalize(); mPos += Vector3.Multiply(direction, speed * dt); mTranslationTimer -= dt; if (mTranslationTimer < 0) { mPos = mTargetPos; mMovementMeter -= mDistance; mArrivedAtDest = true; } } base.Update(); } } }