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