Enemy.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // Enemy.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. using System;
  10. using Microsoft.Xna.Framework;
  11. using Microsoft.Xna.Framework.Graphics;
  12. namespace Platformer
  13. {
  14. /// <summary>
  15. /// Facing direction along the X axis.
  16. /// </summary>
  17. enum FaceDirection
  18. {
  19. Left = -1,
  20. Right = 1,
  21. }
  22. /// <summary>
  23. /// A monster who is impeding the progress of our fearless adventurer.
  24. /// </summary>
  25. class Enemy
  26. {
  27. public Level Level
  28. {
  29. get { return level; }
  30. }
  31. Level level;
  32. /// <summary>
  33. /// Position in world space of the bottom center of this enemy.
  34. /// </summary>
  35. public Vector2 Position
  36. {
  37. get { return position; }
  38. }
  39. Vector2 position;
  40. private Rectangle localBounds;
  41. /// <summary>
  42. /// Gets a rectangle which bounds this enemy in world space.
  43. /// </summary>
  44. public Rectangle BoundingRectangle
  45. {
  46. get
  47. {
  48. int left = (int)Math.Round(Position.X - sprite.Origin.X) + localBounds.X;
  49. int top = (int)Math.Round(Position.Y - sprite.Origin.Y) + localBounds.Y;
  50. return new Rectangle(left, top, localBounds.Width, localBounds.Height);
  51. }
  52. }
  53. // Animations
  54. private Animation runAnimation;
  55. private Animation idleAnimation;
  56. private AnimationPlayer sprite;
  57. /// <summary>
  58. /// The direction this enemy is facing and moving along the X axis.
  59. /// </summary>
  60. private FaceDirection direction = FaceDirection.Left;
  61. /// <summary>
  62. /// How long this enemy has been waiting before turning around.
  63. /// </summary>
  64. private float waitTime;
  65. /// <summary>
  66. /// How long to wait before turning around.
  67. /// </summary>
  68. private const float MaxWaitTime = 0.5f;
  69. /// <summary>
  70. /// The speed at which this enemy moves along the X axis.
  71. /// </summary>
  72. private const float MoveSpeed = 64.0f;
  73. /// <summary>
  74. /// Constructs a new Enemy.
  75. /// </summary>
  76. public Enemy(Level level, Vector2 position, string spriteSet)
  77. {
  78. this.level = level;
  79. this.position = position;
  80. LoadContent(spriteSet);
  81. }
  82. /// <summary>
  83. /// Loads a particular enemy sprite sheet and sounds.
  84. /// </summary>
  85. public void LoadContent(string spriteSet)
  86. {
  87. // Load animations.
  88. spriteSet = "Sprites/" + spriteSet + "/";
  89. runAnimation = new Animation(Level.Content.Load<Texture2D>(spriteSet + "Run"), 0.1f, true);
  90. idleAnimation = new Animation(Level.Content.Load<Texture2D>(spriteSet + "Idle"), 0.15f, true);
  91. sprite.PlayAnimation(idleAnimation);
  92. // Calculate bounds within texture size.
  93. int width = (int)(idleAnimation.FrameWidth * 0.35);
  94. int left = (idleAnimation.FrameWidth - width) / 2;
  95. int height = (int)(idleAnimation.FrameWidth * 0.7);
  96. int top = idleAnimation.FrameHeight - height;
  97. localBounds = new Rectangle(left, top, width, height);
  98. }
  99. /// <summary>
  100. /// Paces back and forth along a platform, waiting at either end.
  101. /// </summary>
  102. public void Update(GameTime gameTime)
  103. {
  104. float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
  105. // Calculate tile position based on the side we are walking towards.
  106. float posX = Position.X + localBounds.Width / 2 * (int)direction;
  107. int tileX = (int)Math.Floor(posX / Tile.Width) - (int)direction;
  108. int tileY = (int)Math.Floor(Position.Y / Tile.Height);
  109. if (waitTime > 0)
  110. {
  111. // Wait for some amount of time.
  112. waitTime = Math.Max(0.0f, waitTime - (float)gameTime.ElapsedGameTime.TotalSeconds);
  113. if (waitTime <= 0.0f)
  114. {
  115. // Then turn around.
  116. direction = (FaceDirection)(-(int)direction);
  117. }
  118. }
  119. else
  120. {
  121. // If we are about to run into a wall or off a cliff, start waiting.
  122. if (Level.GetCollision(tileX + (int)direction, tileY - 1) == TileCollision.Impassable ||
  123. Level.GetCollision(tileX + (int)direction, tileY) == TileCollision.Passable)
  124. {
  125. waitTime = MaxWaitTime;
  126. }
  127. else
  128. {
  129. // Move in the current direction.
  130. Vector2 velocity = new Vector2((int)direction * MoveSpeed * elapsed, 0.0f);
  131. position = position + velocity;
  132. }
  133. }
  134. }
  135. /// <summary>
  136. /// Draws the animated enemy.
  137. /// </summary>
  138. public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
  139. {
  140. // Stop running when the game is paused or before turning around.
  141. if (!Level.Player.IsAlive ||
  142. Level.ReachedExit ||
  143. Level.TimeRemaining == TimeSpan.Zero ||
  144. waitTime > 0)
  145. {
  146. sprite.PlayAnimation(idleAnimation);
  147. }
  148. else
  149. {
  150. sprite.PlayAnimation(runAnimation);
  151. }
  152. // Draw facing the way the enemy is moving.
  153. SpriteEffects flip = direction > 0 ? SpriteEffects.FlipHorizontally : SpriteEffects.None;
  154. sprite.Draw(gameTime, spriteBatch, Position, flip);
  155. }
  156. }
  157. }