Asteroid.cs 6.9 KB

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