#region File Description
//-----------------------------------------------------------------------------
// Ship.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;
using System;
#endregion
namespace Game1
{
class Ship
{
#region Fields
private const float MinimumAltitude = 100.0f;
public float Ground
{
get { return MinimumAltitude; }
}
/// <summary>
/// Location of ship in world space.
/// </summary>
public Vector3 Position;
/// <summary>
/// Direction ship is facing.
/// </summary>
public Vector3 Direction;
private BoundingSphere sphere;
public BoundingSphere Sphere
{
get { return sphere; }
set { sphere = value; /* new BoundingSphere(Position, 0.04f); */ }
}
/// <summary>
/// Ship's up vector.
/// </summary>
public Vector3 Up;
private Vector3 right;
/// <summary>
/// Ship's right vector.
/// </summary>
public Vector3 Right
{
get { return right; }
}
/// <summary>
/// Full speed at which ship can rotate; measured in radians per second.
/// </summary>
private const float RotationRate = 1.5f;
/// <summary>
/// Mass of ship.
/// </summary>
private const float Mass = 1.0f;
/// <summary>
/// Maximum force that can be applied along the ship's direction.
/// </summary>
private const float ThrustForce = 24000.0f;
/// <summary>
/// Velocity scalar to approximate drag.
/// </summary>
private const float DragFactor = 0.97f;
/// <summary>
/// Current ship velocity.
/// </summary>
public Vector3 Velocity;
/// <summary>
/// Ship world transform matrix.
/// </summary>
public Matrix World
{
get { return world; }
}
private Matrix world;
#endregion
#region Initialization
public Ship()
{
Reset();
}
/// <summary>
/// Restore the ship to its original starting state
/// </summary>
public void Reset()
{
Position = new Vector3(600, MinimumAltitude + 50.0f, -200);
Direction = Vector3.Forward;
Up = Vector3.Up;
right = Vector3.Right;
Velocity = Vector3.Zero;
}
#endregion
/// <summary>
/// Applies a simple rotation to the ship and animates position based
/// on simple linear motion physics.
/// </summary>
public void Update(GameTime gameTime, int w, int h)
{
KeyboardState keyboardState = Keyboard.GetState();
GamePadState gamePadState = GamePad.GetState(PlayerIndex.One);
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
// Determine rotation amount from input
Vector2 rotationAmount = -gamePadState.ThumbSticks.Left;
float w2 = (float)w / 2;
float h2 = (float)h / 2;
if (Mouse.GetState().LeftButton == ButtonState.Pressed)
{
rotationAmount.X = ((float)Mouse.GetState().X - w2) / -w2;
rotationAmount.Y = ((float)Mouse.GetState().Y - h2) / -h2;
//rotationAmount.Y = 0;
}
if (keyboardState.IsKeyDown(Keys.Left))
rotationAmount.X = 1.0f;
if (keyboardState.IsKeyDown(Keys.Right))
rotationAmount.X = -1.0f;
if (keyboardState.IsKeyDown(Keys.Up))
rotationAmount.Y = -1.0f;
if (keyboardState.IsKeyDown(Keys.Down))
rotationAmount.Y = 1.0f;
// Scale rotation amount to radians per second
rotationAmount = rotationAmount * RotationRate * elapsed;
// Correct the X axis steering when the ship is upside down
if (Up.Y < 0)
rotationAmount.X = -rotationAmount.X;
// Create rotation matrix from rotation amount
Matrix rotationMatrix =
Matrix.CreateFromAxisAngle(Right, rotationAmount.Y) *
Matrix.CreateRotationY(rotationAmount.X);
// Rotate orientation vectors
Direction = Vector3.TransformNormal(Direction, rotationMatrix);
Up = Vector3.TransformNormal(Up, rotationMatrix);
// Re-normalize orientation vectors
// Without this, the matrix transformations may introduce small rounding
// errors which add up over time and could destabilize the ship.
Direction.Normalize();
Up.Normalize();
// Re-calculate Right
right = Vector3.Cross(Direction, Up);
// The same instability may cause the 3 orientation vectors may
// also diverge. Either the Up or Direction vector needs to be
// re-computed with a cross product to ensure orthagonality
Up = Vector3.Cross(Right, Direction);
// Determine thrust amount from input
float thrustAmount = gamePadState.Triggers.Right;
if (keyboardState.IsKeyDown(Keys.Space))
thrustAmount = 0.10f;
// Calculate force from thrust amount
Vector3 force = Direction * thrustAmount * ThrustForce;
// Apply acceleration
Vector3 acceleration = force / Mass;
Velocity += acceleration * elapsed;
// Apply psuedo drag
Velocity *= DragFactor;
// Apply velocity
Position += Velocity * elapsed;
// Prevent ship from flying under the ground
Position.Y = Math.Max(Position.Y, MinimumAltitude);
// Reconstruct the ship's world matrix
world = Matrix.Identity;
world.Forward = Direction;
world.Up = Up;
world.Right = right;
world.Translation = Position;
sphere = new BoundingSphere(Position, 27.0f);
}
internal void acceleration(ref Vector3 vector3, Vector3 vector3_2, float p)
{
throw new NotImplementedException();
}
}
}