Bee.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // Bee.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. #endregion
  14. namespace HoneycombRush
  15. {
  16. /// <summary>
  17. /// Repesents the base bee component.
  18. /// </summary>
  19. public abstract class Bee : TexturedDrawableGameComponent
  20. {
  21. #region Fields/Properties
  22. protected static Random random = new Random();
  23. protected Beehive relatedBeehive;
  24. protected Vector2 velocity;
  25. protected float rotation;
  26. protected bool isHitBySmoke;
  27. protected bool isGotHit;
  28. protected string AnimationKey { get; set; }
  29. TimeSpan velocityChangeTimer = TimeSpan.Zero;
  30. /// <summary>
  31. /// Timespan used to regenerate the be after it is chased away by smoke
  32. /// </summary>
  33. TimeSpan timeToRegenerate;
  34. /// <summary>
  35. /// Time at which the bee was hit by smoke
  36. /// </summary>
  37. TimeSpan timeHit;
  38. public bool IsBeeHit
  39. {
  40. get
  41. {
  42. return isHitBySmoke;
  43. }
  44. }
  45. public Beehive Beehive
  46. {
  47. get
  48. {
  49. return relatedBeehive;
  50. }
  51. }
  52. protected virtual TimeSpan VelocityChangeInterval
  53. {
  54. get
  55. {
  56. return TimeSpan.FromMilliseconds(500);
  57. }
  58. }
  59. public override Rectangle Bounds
  60. {
  61. get
  62. {
  63. if (texture == null)
  64. {
  65. return default(Rectangle);
  66. }
  67. else
  68. {
  69. // The bee's texture is an animation strip, so we must devide the texture's width by three
  70. // to get the bee's actual width
  71. return new Rectangle((int)position.X, (int)position.Y,
  72. (int)(texture.Width / 3 * scaledSpriteBatch.ScaleVector.X),
  73. (int)(texture.Height * scaledSpriteBatch.ScaleVector.Y));
  74. }
  75. }
  76. }
  77. #endregion
  78. #region Abstract Properties
  79. abstract protected int MaxVelocity { get; }
  80. abstract protected float AccelerationFactor { get; }
  81. #endregion
  82. #region Initialization
  83. /// <summary>
  84. /// Creates a new bee instance.
  85. /// </summary>
  86. /// <param name="game">The game object.</param>
  87. /// <param name="gamePlayScreen">The gameplay screen.</param>
  88. /// <param name="beehive">The related beehive.</param>
  89. public Bee(Game game, GameplayScreen gamePlayScreen, Beehive beehive)
  90. : base(game, gamePlayScreen)
  91. {
  92. this.relatedBeehive = beehive;
  93. DrawOrder = Int32.MaxValue - 20;
  94. }
  95. /// <summary>
  96. /// Initialize the bee's location and animation.
  97. /// </summary>
  98. public override void Initialize()
  99. {
  100. // Start up position
  101. SetStartupPosition();
  102. if (!string.IsNullOrEmpty(AnimationKey))
  103. {
  104. AnimationDefinitions[AnimationKey].PlayFromFrameIndex(0);
  105. }
  106. base.Initialize();
  107. }
  108. #endregion
  109. #region Update
  110. /// <summary>
  111. /// Updates the bee's status.
  112. /// </summary>
  113. /// <param name="gameTime">Game time information.</param>
  114. public override void Update(GameTime gameTime)
  115. {
  116. if (!(gamePlayScreen.IsActive && gamePlayScreen.IsStarted))
  117. {
  118. base.Update(gameTime);
  119. return;
  120. }
  121. // This method will handle the regeneration of bees that were hit by
  122. // smoke
  123. if (!HandleRegeneration(gameTime))
  124. {
  125. return;
  126. }
  127. if (!string.IsNullOrEmpty(AnimationKey))
  128. {
  129. AnimationDefinitions[AnimationKey].Update(gameTime, true);
  130. }
  131. // If a bee is hit by smoke, it doesn't have random movement until
  132. // regeneration
  133. if (!isHitBySmoke)
  134. {
  135. SetRandomMovement(gameTime);
  136. }
  137. // Moving the bee according to its velocity
  138. position += velocity * scaledSpriteBatch.ScaleVector;
  139. // If the bee is hit by smoke make it bee move faster
  140. if (isHitBySmoke)
  141. {
  142. position += velocity * scaledSpriteBatch.ScaleVector;
  143. }
  144. // If the bee is out of screen
  145. if (position.X < 0 || position.X > Game.GraphicsDevice.Viewport.Width - Bounds.Width ||
  146. position.Y < 0 || position.Y > Game.GraphicsDevice.Viewport.Height - Bounds.Height)
  147. {
  148. if (isHitBySmoke)
  149. {
  150. // Reset the bee's position
  151. SetStartupPositionWithTimer();
  152. }
  153. else
  154. {
  155. // When hit by the screen bounds, we want the bee to move
  156. // longer than usual before picking a new direction
  157. velocityChangeTimer = TimeSpan.FromMilliseconds(-160);
  158. if (position.X < Bounds.Width || position.X > Game.GraphicsDevice.Viewport.Width - Bounds.Width)
  159. {
  160. velocity = new Vector2(velocity.X *= -1, velocity.Y);
  161. }
  162. else
  163. {
  164. velocity = new Vector2(velocity.X, velocity.Y *= -1);
  165. }
  166. }
  167. }
  168. base.Update(gameTime);
  169. }
  170. #endregion
  171. #region Render
  172. /// <summary>
  173. /// Renders the bee.
  174. /// </summary>
  175. /// <param name="gameTime">Game time information.</param>
  176. public override void Draw(GameTime gameTime)
  177. {
  178. if (gamePlayScreen.IsActive && gamePlayScreen.IsStarted)
  179. {
  180. scaledSpriteBatch.Begin();
  181. // If the bee has an animation, draw it
  182. if (!string.IsNullOrEmpty(AnimationKey))
  183. {
  184. AnimationDefinitions[AnimationKey].Draw(scaledSpriteBatch, position, SpriteEffects.None);
  185. }
  186. else
  187. {
  188. scaledSpriteBatch.Draw(texture, position, null, Color.White, 0, Vector2.Zero, 1f,
  189. SpriteEffects.None, 0);
  190. }
  191. scaledSpriteBatch.End();
  192. }
  193. base.Draw(gameTime);
  194. }
  195. #endregion
  196. #region Public Methods
  197. /// <summary>
  198. /// Denotes that the bee has been hit by smoke.
  199. /// </summary>
  200. /// <param name="smokePuff">The smoke puff which the be was hit by.</param>
  201. public void HitBySmoke(SmokePuff smokePuff)
  202. {
  203. if (!isHitBySmoke)
  204. {
  205. // Causes the bee to fly away from the smoke puff
  206. Vector2 escapeVector = Bounds.Center.GetVector() - smokePuff.Bounds.Center.GetVector();
  207. escapeVector.Normalize();
  208. escapeVector *= random.Next(3, 6);
  209. velocity = escapeVector;
  210. isHitBySmoke = true;
  211. }
  212. }
  213. /// <summary>
  214. /// Sets the startup position for the bee.
  215. /// </summary>
  216. public virtual void SetStartupPosition()
  217. {
  218. if (relatedBeehive.AllowBeesToGenerate)
  219. {
  220. Rectangle rect = relatedBeehive.Bounds;
  221. position = new Vector2(rect.Center.X, rect.Center.Y);
  222. velocity = new Vector2(random.Next(-MaxVelocity * 100, MaxVelocity * 100) / 100,
  223. random.Next(-MaxVelocity * 100, MaxVelocity * 100) / 100);
  224. isHitBySmoke = false;
  225. timeToRegenerate = TimeSpan.Zero;
  226. timeHit = TimeSpan.Zero;
  227. }
  228. }
  229. /// <summary>
  230. /// Checks collision with a specified rectangle.
  231. /// </summary>
  232. /// <param name="bounds">Rectabgke with which to check for collisions.</param>
  233. public void Collide(Rectangle bounds)
  234. {
  235. // Check if this collision is new
  236. if (!isGotHit)
  237. {
  238. // Moves to new dircetion calculted by the "wall" that the bee collided
  239. // with.
  240. velocityChangeTimer = TimeSpan.FromMilliseconds(-300);
  241. if (position.X < bounds.X || position.X > bounds.X + bounds.Width)
  242. {
  243. velocity = new Vector2(velocity.X *= -1, velocity.Y);
  244. }
  245. else
  246. {
  247. velocity = new Vector2(velocity.X, velocity.Y *= -1);
  248. }
  249. isGotHit = true;
  250. }
  251. }
  252. #endregion
  253. #region Private Methods
  254. /// <summary>
  255. /// Set a timer which will cause the be to regenerate when it expires.
  256. /// </summary>
  257. private void SetStartupPositionWithTimer()
  258. {
  259. timeToRegenerate = TimeSpan.FromMilliseconds(random.Next(3000, 5000));
  260. }
  261. /// <summary>
  262. /// This method handles a bee's regeneration.
  263. /// </summary>
  264. /// <param name="gameTime">Game time information.</param>
  265. /// <returns>True if the bee has regenerated or no regeneration was necessary,
  266. /// false otherwise.</returns>
  267. private bool HandleRegeneration(GameTime gameTime)
  268. {
  269. // Checks if regeneration is needed
  270. if (timeToRegenerate != TimeSpan.Zero)
  271. {
  272. // Saves the time the bee was hit
  273. if (timeHit == TimeSpan.Zero)
  274. {
  275. timeHit = gameTime.TotalGameTime;
  276. }
  277. // If enough time has pass, regenerate the bee
  278. if (timeToRegenerate + timeHit < gameTime.TotalGameTime)
  279. {
  280. SetStartupPosition();
  281. }
  282. else
  283. {
  284. position = new Vector2(-texture.Width, -texture.Height);
  285. return false;
  286. }
  287. }
  288. return true;
  289. }
  290. /// <summary>
  291. /// Alter the bee's movement randomly.
  292. /// </summary>
  293. /// <param name="gameTime">Game time information.</param>
  294. private void SetRandomMovement(GameTime gameTime)
  295. {
  296. velocityChangeTimer += gameTime.ElapsedGameTime;
  297. if (velocityChangeTimer >= VelocityChangeInterval)
  298. {
  299. velocity = new Vector2(random.Next(-MaxVelocity * 100, MaxVelocity * 100) / 100,
  300. random.Next(-MaxVelocity * 100, MaxVelocity * 100) / 100);
  301. velocityChangeTimer = TimeSpan.Zero;
  302. if (isGotHit)
  303. {
  304. isGotHit = false;
  305. }
  306. }
  307. }
  308. #endregion
  309. }
  310. }