| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- #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 ChaseCameraSample
- {
- class Ship
- {
- #region Fields
- private const float MinimumAltitude = 350.0f;
- /// <summary>
- /// A reference to the graphics device used to access the viewport for touch input.
- /// </summary>
- private GraphicsDevice graphicsDevice;
- /// <summary>
- /// Location of ship in world space.
- /// </summary>
- public Vector3 Position;
- /// <summary>
- /// Direction ship is facing.
- /// </summary>
- public Vector3 Direction;
- /// <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(GraphicsDevice device)
- {
- graphicsDevice = device;
- Reset();
- }
- /// <summary>
- /// Restore the ship to its original starting state
- /// </summary>
- public void Reset()
- {
- Position = new Vector3(0, MinimumAltitude, 0);
- Direction = Vector3.Forward;
- Up = Vector3.Up;
- right = Vector3.Right;
- Velocity = Vector3.Zero;
- }
- #endregion
- bool TouchLeft()
- {
- MouseState mouseState = Mouse.GetState();
- return mouseState.LeftButton == ButtonState.Pressed &&
- mouseState.X <= graphicsDevice.Viewport.Width / 3;
- }
- bool TouchRight()
- {
- MouseState mouseState = Mouse.GetState();
- return mouseState.LeftButton == ButtonState.Pressed &&
- mouseState.X >= 2 * graphicsDevice.Viewport.Width / 3;
- }
- bool TouchDown()
- {
- MouseState mouseState = Mouse.GetState();
- return mouseState.LeftButton == ButtonState.Pressed &&
- mouseState.Y <= graphicsDevice.Viewport.Height / 3;
- }
- bool TouchUp()
- {
- MouseState mouseState = Mouse.GetState();
- return mouseState.LeftButton == ButtonState.Pressed &&
- mouseState.Y >= 2 * graphicsDevice.Viewport.Height / 3;
- }
- /// <summary>
- /// Applies a simple rotation to the ship and animates position based
- /// on simple linear motion physics.
- /// </summary>
- public void Update(GameTime gameTime)
- {
- KeyboardState keyboardState = Keyboard.GetState();
- GamePadState gamePadState = GamePad.GetState(PlayerIndex.One);
- MouseState mouseState = Mouse.GetState();
- float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
- // Determine rotation amount from input
- Vector2 rotationAmount = -gamePadState.ThumbSticks.Left;
- if (keyboardState.IsKeyDown(Keys.Left) || TouchLeft())
- rotationAmount.X = 1.0f;
- if (keyboardState.IsKeyDown(Keys.Right) || TouchRight())
- rotationAmount.X = -1.0f;
- if (keyboardState.IsKeyDown(Keys.Up) || TouchUp())
- rotationAmount.Y = -1.0f;
- if (keyboardState.IsKeyDown(Keys.Down) || TouchDown())
- 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) || mouseState.LeftButton == ButtonState.Pressed)
- thrustAmount = 1.0f;
- // 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;
- }
- }
- }
|