Asteroid.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // Asteroid.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 System;
  11. using Microsoft.Xna.Framework;
  12. using Microsoft.Xna.Framework.Graphics;
  13. using Microsoft.Xna.Framework.Content;
  14. #endregion
  15. namespace NetRumble
  16. {
  17. /// <summary>
  18. /// Asteroids that fill the game world, blocking the player's shots and movements.
  19. /// </summary>
  20. public class Asteroid : GameplayObject
  21. {
  22. #region Constants
  23. /// <summary>
  24. /// The ratio of the mass of an asteroid to its radius.
  25. /// </summary>
  26. const float massRadiusRatio = 0.5f;
  27. /// <summary>
  28. /// The amount of drag applied to velocity per second,
  29. /// as a percentage of velocity.
  30. /// </summary>
  31. const float dragPerSecond = 0.15f;
  32. /// <summary>
  33. /// Scalar to convert the velocity / mass ratio into a "nice" rotational value.
  34. /// </summary>
  35. const float velocityMassRatioToRotationScalar = 0.0017f;
  36. /// <summary>
  37. /// Scalar for calculated damage values that asteroids apply to players.
  38. /// </summary>
  39. const float momentumToDamageScalar = 0.007f;
  40. /// <summary>
  41. /// The number of variations in textures for asteroids.
  42. /// </summary>
  43. const int variations = 3;
  44. /// <summary>
  45. /// The minimum possible initial speed for asteroids.
  46. /// </summary>
  47. const float initialSpeedMinimum = 32f;
  48. /// <summary>
  49. /// The minimum possible initial speed for asteroids.
  50. /// </summary>
  51. const float initialSpeedMaximum = 96f;
  52. #endregion
  53. #region Static Graphics Data
  54. /// <summary>
  55. /// The asteroid textures.
  56. /// </summary>
  57. private static Texture2D[] textures = new Texture2D[variations];
  58. #endregion
  59. #region Graphics Data
  60. /// <summary>
  61. /// The variation of this particular asteroid.
  62. /// </summary>
  63. private int variation = 0;
  64. public int Variation
  65. {
  66. get { return variation; }
  67. set
  68. {
  69. if ((value < 0) || (value >= variations))
  70. {
  71. throw new ArgumentOutOfRangeException("value");
  72. }
  73. variation = value;
  74. }
  75. }
  76. #endregion
  77. #region Initialization Methods
  78. /// <summary>
  79. /// Construct a new asteroid.
  80. /// </summary>
  81. /// <param name="world">The world that this asteroid belongs to.</param>
  82. /// <param name="radius">The size of the asteroid.</param>
  83. public Asteroid(float radius)
  84. : base()
  85. {
  86. // safety-check the parameters
  87. if (radius <= 0f)
  88. {
  89. throw new ArgumentOutOfRangeException("radius");
  90. }
  91. // set the collision data
  92. this.radius = radius;
  93. this.mass = this.radius * massRadiusRatio;
  94. this.Velocity = RandomMath.RandomDirection() *
  95. RandomMath.RandomBetween(initialSpeedMinimum, initialSpeedMaximum);
  96. }
  97. #endregion
  98. #region Updating Methods
  99. /// <summary>
  100. /// Update the asteroid.
  101. /// </summary>
  102. /// <param name="elapsedTime">The amount of elapsed time, in seconds.</param>
  103. public override void Update(float elapsedTime)
  104. {
  105. // spin the asteroid based on the radius and velocity
  106. float velocityMassRatio = (Velocity.LengthSquared() / Mass);
  107. rotation += velocityMassRatio * velocityMassRatioToRotationScalar *
  108. elapsedTime;
  109. // apply some drag so the asteroids settle down
  110. Velocity -= Velocity * (elapsedTime * dragPerSecond);
  111. base.Update(elapsedTime);
  112. }
  113. #endregion
  114. #region Drawing Methods
  115. /// <summary>
  116. /// Draw the asteroid.
  117. /// </summary>
  118. /// <param name="elapsedTime">The amount of elapsed time, in seconds.</param>
  119. /// <param name="spriteBatch">The SpriteBatch object used to draw.</param>
  120. public void Draw(float elapsedTime, SpriteBatch spriteBatch)
  121. {
  122. base.Draw(elapsedTime, spriteBatch, textures[variation], null,
  123. Color.White);
  124. }
  125. #endregion
  126. #region Interaction Methods
  127. /// <summary>
  128. /// Defines the interaction between the asteroid and a target GameplayObject
  129. /// when they touch.
  130. /// </summary>
  131. /// <param name="target">The GameplayObject that is touching this one.</param>
  132. /// <returns>True if the objects meaningfully interacted.</returns>
  133. public override bool Touch(GameplayObject target)
  134. {
  135. // if the asteroid has touched a player, then damage it
  136. Ship player = target as Ship;
  137. if (player != null)
  138. {
  139. // calculate damage as a function of how much the two GameplayObject's
  140. // velocities were going towards one another
  141. Vector2 playerAsteroidVector = Position - player.Position;
  142. if (playerAsteroidVector.LengthSquared() > 0)
  143. {
  144. playerAsteroidVector.Normalize();
  145. float rammingSpeed =
  146. Vector2.Dot(playerAsteroidVector, player.Velocity) -
  147. Vector2.Dot(playerAsteroidVector, Velocity);
  148. float momentum = Mass * rammingSpeed;
  149. player.Damage(this, momentum * momentumToDamageScalar);
  150. }
  151. }
  152. // if the asteroid didn't hit a projectile, play the asteroid-touch sound effect
  153. if ((target is Projectile) == false)
  154. {
  155. AudioManager.PlaySoundEffect("asteroid_touch");
  156. }
  157. return true;
  158. }
  159. #endregion
  160. #region Static Graphics Methods
  161. /// <summary>
  162. /// The number of variations in asteroids.
  163. /// </summary>
  164. public static int Variations
  165. {
  166. get { return variations; }
  167. }
  168. /// <summary>
  169. /// Load all of the static graphics content for this class.
  170. /// </summary>
  171. /// <param name="contentManager">The content manager to load with.</param>
  172. public static void LoadContent(ContentManager contentManager)
  173. {
  174. // safety-check the parameters
  175. if (contentManager == null)
  176. {
  177. throw new ArgumentNullException("contentManager");
  178. }
  179. // load each asteroid's texture
  180. for (int i = 0; i < variations; i++)
  181. {
  182. textures[i] = contentManager.Load<Texture2D>(
  183. "Textures/asteroid" + i.ToString());
  184. }
  185. }
  186. /// <summary>
  187. /// Unload all of the static graphics content for this class.
  188. /// </summary>
  189. public static void UnloadContent()
  190. {
  191. for (int i = 0; i < variations; i++)
  192. {
  193. textures[i] = null;
  194. }
  195. }
  196. #endregion
  197. }
  198. }