Projectile.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // Projectile.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 System.Collections.Generic;
  12. using System.Text;
  13. using Microsoft.Xna.Framework;
  14. #endregion
  15. namespace Spacewar
  16. {
  17. /// <summary>
  18. /// Represents a projectile in SpacewarGame - retro or evolved
  19. /// </summary>
  20. public class Projectile : SpacewarSceneItem
  21. {
  22. private static int[] projectileCount = new int[3];
  23. /// <summary>
  24. /// Which player this projectile came from
  25. /// </summary>
  26. private PlayerIndex player;
  27. /// <summary>
  28. /// The damage that this bullet does
  29. /// </summary>
  30. private int damage;
  31. private double endTime;
  32. private int projectileType;
  33. private bool exploded = false;
  34. private Particles particles;
  35. private bool projectileArmed;
  36. private Vector3 thrust;
  37. #region Properties
  38. public static int[] ProjectileCount
  39. {
  40. get
  41. {
  42. return projectileCount;
  43. }
  44. }
  45. public int Damage
  46. {
  47. get
  48. {
  49. return damage;
  50. }
  51. }
  52. #endregion
  53. /// <summary>
  54. /// Cretes a new projectile
  55. /// </summary>
  56. /// <param name="game">Instance of the game</param>
  57. /// <param name="player">Which player it came from</param>
  58. /// <param name="position">The start position</param>
  59. /// <param name="velocity">The start velocity</param>
  60. /// <param name="angle">The direction its facing</param>
  61. /// <param name="time">The time the projectile was fired</param>
  62. public Projectile(Game game, PlayerIndex player, Vector3 position, Vector3 velocity, float angle, TimeSpan time, Particles particles)
  63. : base(game)
  64. {
  65. this.player = player;
  66. this.velocity = velocity;
  67. this.position = position;
  68. projectileCount[(int)player]++;
  69. if (SpacewarGame.GameState == GameState.PlayEvolved)
  70. {
  71. projectileType = (int)SpacewarGame.Players[(int)player].ProjectileType;
  72. this.particles = particles;
  73. endTime = time.TotalSeconds + SpacewarGame.Settings.Weapons[projectileType].Lifetime;
  74. thrust = Vector3.Multiply(Vector3.Normalize(velocity), SpacewarGame.Settings.Weapons[projectileType].Acceleration);
  75. radius = 2;
  76. damage = SpacewarGame.Settings.Weapons[projectileType].Damage;
  77. if (SpacewarGame.GameState == GameState.PlayEvolved)
  78. {
  79. shape = new BasicEffectShape(GameInstance, BasicEffectShapes.Projectile, projectileType, LightingType.InGame);
  80. //Evolved needs scaling
  81. scale.X =
  82. scale.Y =
  83. scale.Z = SpacewarGame.Settings.BulletScale;
  84. rotation.X = MathHelper.ToRadians(90);
  85. rotation.Y = 0;
  86. rotation.Z = (float)angle;
  87. }
  88. }
  89. else
  90. {
  91. //Build up a retro weapon
  92. damage = 5; //One shot kill
  93. projectileType = (int)ProjectileType.Peashooter;
  94. radius = 1;
  95. endTime = time.TotalSeconds + 2.0;
  96. acceleration = Vector3.Zero;
  97. }
  98. //Play 'shoot' sound
  99. switch (projectileType)
  100. {
  101. case (int)ProjectileType.Peashooter:
  102. Sound.PlayCue(Sounds.PeashooterFire);
  103. break;
  104. case (int)ProjectileType.MachineGun:
  105. Sound.PlayCue(Sounds.MachineGunFire);
  106. break;
  107. case (int)ProjectileType.DoubleMachineGun:
  108. Sound.PlayCue(Sounds.DoubleMachineGunFire);
  109. break;
  110. case (int)ProjectileType.Rocket:
  111. Sound.PlayCue(Sounds.RocketExplode);
  112. break;
  113. case (int)ProjectileType.BFG:
  114. Sound.PlayCue(Sounds.BFGFire);
  115. break;
  116. }
  117. }
  118. /// <summary>
  119. /// Updates the bullet. Removes it from scene when item is timed out
  120. /// </summary>
  121. /// <param name="time">Current game time</param>
  122. /// <param name="elapsedTime">Elapsed time since last update</param>
  123. public override void Update(TimeSpan time, TimeSpan elapsedTime)
  124. {
  125. //See if this bullets lifespan has expired
  126. if (time.TotalSeconds > endTime)
  127. {
  128. //BFG explodes and has a blast radius
  129. if (SpacewarGame.GameState == GameState.PlayEvolved && projectileType == 4 && !exploded)
  130. {
  131. Sound.PlayCue(Sounds.Explosion);
  132. particles.AddExplosion(Position);
  133. //We don't delete it this frame but we change the radius and the damage
  134. exploded = true;
  135. radius = 30;
  136. damage = 3;
  137. }
  138. else
  139. {
  140. DeleteProjectile();
  141. }
  142. }
  143. acceleration = thrust;
  144. //For the rocket we need particles
  145. if (projectileType == 3)
  146. {
  147. particles.AddRocketTrail(shape.World, new Vector2(acceleration.X, -acceleration.Y));
  148. }
  149. base.Update(time, elapsedTime);
  150. }
  151. public void DeleteProjectile()
  152. {
  153. if (!delete)
  154. projectileCount[(int)player]--;
  155. delete = true;
  156. }
  157. /// <summary>
  158. /// Checks if there is a collision between the this and the passed in item
  159. /// </summary>
  160. /// <param name="item">A scene item to check</param>
  161. /// <returns>True if there is a collision</returns>
  162. public override bool Collide(SceneItem item)
  163. {
  164. // Until we get collision meshes sorted just do a simple sphere (well circle!) check
  165. float currentDistance = (Position - item.Position).Length();
  166. bool colliding = base.Collide(item);
  167. // For projectiles, do not allow them to destroy the ship that just fired them!
  168. Ship shipItem = item as Ship;
  169. if ((shipItem != null) && (shipItem.Player == player))
  170. {
  171. if (colliding && !projectileArmed)
  172. {
  173. colliding = false;
  174. }
  175. else if (!colliding && !projectileArmed)
  176. {
  177. // Once projectile is at least 2 ship radii away, it can arm!
  178. // This is becuase the bolt launches with your velocity at the time
  179. // and the ship can "catch up" to the bolt pretty easily if you are
  180. // thrusting in the direction you are firing.
  181. if (currentDistance > item.Radius * 2.0f)
  182. projectileArmed = true;
  183. }
  184. }
  185. return colliding;
  186. }
  187. }
  188. }