Ship.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // Ship.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using Microsoft.Xna.Framework;
  11. using Microsoft.Xna.Framework.Graphics;
  12. using Microsoft.Xna.Framework.Input;
  13. using Microsoft.Xna.Framework.Content;
  14. using System;
  15. #endregion
  16. namespace ChaseCameraSample
  17. {
  18. class Ship
  19. {
  20. #region Fields
  21. private const float MinimumAltitude = 350.0f;
  22. /// <summary>
  23. /// A reference to the graphics device used to access the viewport for touch input.
  24. /// </summary>
  25. private GraphicsDevice graphicsDevice;
  26. /// <summary>
  27. /// Location of ship in world space.
  28. /// </summary>
  29. public Vector3 Position;
  30. /// <summary>
  31. /// Direction ship is facing.
  32. /// </summary>
  33. public Vector3 Direction;
  34. /// <summary>
  35. /// Ship's up vector.
  36. /// </summary>
  37. public Vector3 Up;
  38. private Vector3 right;
  39. /// <summary>
  40. /// Ship's right vector.
  41. /// </summary>
  42. public Vector3 Right
  43. {
  44. get { return right; }
  45. }
  46. /// <summary>
  47. /// Full speed at which ship can rotate; measured in radians per second.
  48. /// </summary>
  49. private const float RotationRate = 1.5f;
  50. /// <summary>
  51. /// Mass of ship.
  52. /// </summary>
  53. private const float Mass = 1.0f;
  54. /// <summary>
  55. /// Maximum force that can be applied along the ship's direction.
  56. /// </summary>
  57. private const float ThrustForce = 24000.0f;
  58. /// <summary>
  59. /// Velocity scalar to approximate drag.
  60. /// </summary>
  61. private const float DragFactor = 0.97f;
  62. /// <summary>
  63. /// Current ship velocity.
  64. /// </summary>
  65. public Vector3 Velocity;
  66. /// <summary>
  67. /// Ship world transform matrix.
  68. /// </summary>
  69. public Matrix World
  70. {
  71. get { return world; }
  72. }
  73. private Matrix world;
  74. #endregion
  75. #region Initialization
  76. public Ship(GraphicsDevice device)
  77. {
  78. graphicsDevice = device;
  79. Reset();
  80. }
  81. /// <summary>
  82. /// Restore the ship to its original starting state
  83. /// </summary>
  84. public void Reset()
  85. {
  86. Position = new Vector3(0, MinimumAltitude, 0);
  87. Direction = Vector3.Forward;
  88. Up = Vector3.Up;
  89. right = Vector3.Right;
  90. Velocity = Vector3.Zero;
  91. }
  92. #endregion
  93. bool TouchLeft()
  94. {
  95. MouseState mouseState = Mouse.GetState();
  96. return mouseState.LeftButton == ButtonState.Pressed &&
  97. mouseState.X <= graphicsDevice.Viewport.Width / 3;
  98. }
  99. bool TouchRight()
  100. {
  101. MouseState mouseState = Mouse.GetState();
  102. return mouseState.LeftButton == ButtonState.Pressed &&
  103. mouseState.X >= 2 * graphicsDevice.Viewport.Width / 3;
  104. }
  105. bool TouchDown()
  106. {
  107. MouseState mouseState = Mouse.GetState();
  108. return mouseState.LeftButton == ButtonState.Pressed &&
  109. mouseState.Y <= graphicsDevice.Viewport.Height / 3;
  110. }
  111. bool TouchUp()
  112. {
  113. MouseState mouseState = Mouse.GetState();
  114. return mouseState.LeftButton == ButtonState.Pressed &&
  115. mouseState.Y >= 2 * graphicsDevice.Viewport.Height / 3;
  116. }
  117. /// <summary>
  118. /// Applies a simple rotation to the ship and animates position based
  119. /// on simple linear motion physics.
  120. /// </summary>
  121. public void Update(GameTime gameTime)
  122. {
  123. KeyboardState keyboardState = Keyboard.GetState();
  124. GamePadState gamePadState = GamePad.GetState(PlayerIndex.One);
  125. MouseState mouseState = Mouse.GetState();
  126. float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
  127. // Determine rotation amount from input
  128. Vector2 rotationAmount = -gamePadState.ThumbSticks.Left;
  129. if (keyboardState.IsKeyDown(Keys.Left) || TouchLeft())
  130. rotationAmount.X = 1.0f;
  131. if (keyboardState.IsKeyDown(Keys.Right) || TouchRight())
  132. rotationAmount.X = -1.0f;
  133. if (keyboardState.IsKeyDown(Keys.Up) || TouchUp())
  134. rotationAmount.Y = -1.0f;
  135. if (keyboardState.IsKeyDown(Keys.Down) || TouchDown())
  136. rotationAmount.Y = 1.0f;
  137. // Scale rotation amount to radians per second
  138. rotationAmount = rotationAmount * RotationRate * elapsed;
  139. // Correct the X axis steering when the ship is upside down
  140. if (Up.Y < 0)
  141. rotationAmount.X = -rotationAmount.X;
  142. // Create rotation matrix from rotation amount
  143. Matrix rotationMatrix =
  144. Matrix.CreateFromAxisAngle(Right, rotationAmount.Y) *
  145. Matrix.CreateRotationY(rotationAmount.X);
  146. // Rotate orientation vectors
  147. Direction = Vector3.TransformNormal(Direction, rotationMatrix);
  148. Up = Vector3.TransformNormal(Up, rotationMatrix);
  149. // Re-normalize orientation vectors
  150. // Without this, the matrix transformations may introduce small rounding
  151. // errors which add up over time and could destabilize the ship.
  152. Direction.Normalize();
  153. Up.Normalize();
  154. // Re-calculate Right
  155. right = Vector3.Cross(Direction, Up);
  156. // The same instability may cause the 3 orientation vectors may
  157. // also diverge. Either the Up or Direction vector needs to be
  158. // re-computed with a cross product to ensure orthagonality
  159. Up = Vector3.Cross(Right, Direction);
  160. // Determine thrust amount from input
  161. float thrustAmount = gamePadState.Triggers.Right;
  162. if (keyboardState.IsKeyDown(Keys.Space) || mouseState.LeftButton == ButtonState.Pressed)
  163. thrustAmount = 1.0f;
  164. // Calculate force from thrust amount
  165. Vector3 force = Direction * thrustAmount * ThrustForce;
  166. // Apply acceleration
  167. Vector3 acceleration = force / Mass;
  168. Velocity += acceleration * elapsed;
  169. // Apply psuedo drag
  170. Velocity *= DragFactor;
  171. // Apply velocity
  172. Position += Velocity * elapsed;
  173. // Prevent ship from flying under the ground
  174. Position.Y = Math.Max(Position.Y, MinimumAltitude);
  175. // Reconstruct the ship's world matrix
  176. world = Matrix.Identity;
  177. world.Forward = Direction;
  178. world.Up = Up;
  179. world.Right = right;
  180. world.Translation = Position;
  181. }
  182. }
  183. }