SmokePuff.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // SmokePuff.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. using Microsoft.Xna.Framework.Graphics;
  15. #endregion
  16. namespace HoneycombRush
  17. {
  18. /// <summary>
  19. /// Represents a puff of smoke fired from the beekeeper's smoke gun.
  20. /// </summary>
  21. /// <remarks>Smoke puffs add and remove themselves from the list of game components as appropriate.</remarks>
  22. public class SmokePuff : TexturedDrawableGameComponent
  23. {
  24. #region Fields/Properties
  25. readonly TimeSpan growthTimeInterval = TimeSpan.FromMilliseconds(50);
  26. const float growthStep = 0.05f;
  27. TimeSpan lifeTime;
  28. TimeSpan growthTimeTrack;
  29. /// <summary>
  30. /// Used to scale the smoke puff
  31. /// </summary>
  32. float spreadFactor;
  33. Vector2 initialVelocity;
  34. Vector2 velocity;
  35. Vector2 acceleration;
  36. Vector2 drawOrigin;
  37. Random random = new Random();
  38. public bool IsGone
  39. {
  40. get
  41. {
  42. return lifeTime <= TimeSpan.Zero;
  43. }
  44. }
  45. bool isInGameComponents;
  46. /// <summary>
  47. /// Represents an area used for collision calculations.
  48. /// </summary>
  49. public override Rectangle CentralCollisionArea
  50. {
  51. get
  52. {
  53. int boundsWidth = (int)(texture.Width * spreadFactor * 1.5f * scaledSpriteBatch.ScaleVector.X);
  54. int boundsHeight = (int)(texture.Height * spreadFactor * 1.5f * scaledSpriteBatch.ScaleVector.Y);
  55. return new Rectangle((int)position.X - boundsWidth / 4, (int)position.Y - boundsHeight / 4,
  56. boundsWidth, boundsHeight);
  57. }
  58. }
  59. #endregion
  60. #region Initialization
  61. /// <summary>
  62. /// Creates a new puff of smoke.
  63. /// </summary>
  64. /// <param name="game">Associated game object.</param>
  65. /// <param name="gameplayScreen">The gameplay screen where the smoke puff will be displayed.</param>
  66. /// <param name="texture">The texture which represents the smoke puff.</param>
  67. public SmokePuff(Game game, GameplayScreen gameplayScreen, Texture2D texture)
  68. : base(game, gameplayScreen)
  69. {
  70. this.texture = texture;
  71. drawOrigin = new Vector2(texture.Width / 2, texture.Height / 2);
  72. DrawOrder = Int32.MaxValue - 15;
  73. }
  74. /// <summary>
  75. /// Fires the smoke puff from a specified position and at a specified velocity. This also adds the smoke puff
  76. /// to the game component collection.
  77. /// </summary>
  78. /// <param name="origin">The position where the smoke puff should first appear.</param>
  79. /// <param name="initialVelocity">A vector indicating the initial velocity for this new smoke puff.</param>
  80. /// <remarks>The smoke puff's acceleration is internaly derived from
  81. /// <paramref name="initialVelocity"/>.
  82. /// This method is not thread safe and calling it from another thread while the smoke puff expires (via
  83. /// its <see cref="Update"/> method) might have undesired effects.</remarks>
  84. public void Fire(Vector2 origin, Vector2 initialVelocity)
  85. {
  86. spreadFactor = 0.05f;
  87. lifeTime = TimeSpan.FromSeconds(5);
  88. growthTimeTrack = TimeSpan.Zero;
  89. position = origin;
  90. velocity = initialVelocity;
  91. this.initialVelocity = initialVelocity;
  92. initialVelocity.Normalize();
  93. acceleration = -(initialVelocity) * 6;
  94. if (!isInGameComponents)
  95. {
  96. Game.Components.Add(this);
  97. isInGameComponents = true;
  98. }
  99. }
  100. #endregion
  101. #region Update
  102. /// <summary>
  103. /// Performs update logic for the smoke puff. The smoke puff slows down while growing and eventually
  104. /// evaporates.
  105. /// </summary>
  106. /// <param name="gameTime">Game time information.</param>
  107. public override void Update(GameTime gameTime)
  108. {
  109. if (!gamePlayScreen.IsActive)
  110. {
  111. base.Update(gameTime);
  112. return;
  113. }
  114. lifeTime -= gameTime.ElapsedGameTime;
  115. // The smoke puff needs to vanish
  116. if (lifeTime <= TimeSpan.Zero)
  117. {
  118. Game.Components.Remove(this);
  119. isInGameComponents = false;
  120. base.Update(gameTime);
  121. return;
  122. }
  123. growthTimeTrack += gameTime.ElapsedGameTime;
  124. // See if it is time for the smoke puff to grow
  125. if ((spreadFactor < 1) && (growthTimeTrack >= growthTimeInterval))
  126. {
  127. growthTimeTrack = TimeSpan.Zero;
  128. spreadFactor += growthStep;
  129. }
  130. // Stop the smoke once it starts moving in the other direction
  131. if (Vector2.Dot(initialVelocity, velocity) > 0)
  132. {
  133. position += velocity;
  134. velocity += acceleration * (float)gameTime.ElapsedGameTime.TotalSeconds;
  135. }
  136. base.Update(gameTime);
  137. }
  138. #endregion
  139. #region Render
  140. /// <summary>
  141. /// Draws the smoke puff.
  142. /// </summary>
  143. /// <param name="gameTime">Game time information.</param>
  144. public override void Draw(GameTime gameTime)
  145. {
  146. if (!gamePlayScreen.IsActive)
  147. {
  148. base.Draw(gameTime);
  149. return;
  150. }
  151. scaledSpriteBatch.Begin();
  152. Vector2 offset = GetRandomOffset();
  153. scaledSpriteBatch.Draw(texture, position + offset, null, Color.White, 0, drawOrigin, spreadFactor,
  154. SpriteEffects.None, 0);
  155. scaledSpriteBatch.End();
  156. base.Draw(gameTime);
  157. }
  158. /// <summary>
  159. /// Used to make the smoke puff shift randomly.
  160. /// </summary>
  161. /// <returns>An offset which should be added to the smoke puff's position.</returns>
  162. private Vector2 GetRandomOffset()
  163. {
  164. return new Vector2(random.Next(2) - 4, random.Next(2) - 4);
  165. }
  166. #endregion
  167. }
  168. }