ScaledAnimation.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // ScaledAnimation.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region File Information
  10. //-----------------------------------------------------------------------------
  11. // ScaledAnimation.cs
  12. //
  13. // Microsoft XNA Community Game Platform
  14. // Copyright (C) Microsoft Corporation. All rights reserved.
  15. //-----------------------------------------------------------------------------
  16. #endregion
  17. #region Using Statements
  18. using System;
  19. using Microsoft.Xna.Framework;
  20. using Microsoft.Xna.Framework.Graphics;
  21. #endregion
  22. namespace HoneycombRush
  23. {
  24. /// <summary>
  25. /// Supports animation playback.
  26. /// </summary>
  27. public class ScaledAnimation
  28. {
  29. #region Fields
  30. Texture2D animatedCharacter;
  31. Point sheetSize;
  32. public Point currentFrame;
  33. public Point frameSize;
  34. private TimeSpan lastestChangeTime;
  35. private TimeSpan timeInterval = TimeSpan.Zero;
  36. private int startFrame;
  37. private int endFrame;
  38. private int lastSubFrame = -1;
  39. bool drawWasAlreadyCalledOnce = false;
  40. public int FrameCount
  41. {
  42. get
  43. {
  44. return sheetSize.X * sheetSize.Y;
  45. }
  46. }
  47. public Vector2 Offset { get; set; }
  48. public int FrameIndex
  49. {
  50. get
  51. {
  52. return sheetSize.X * currentFrame.Y + currentFrame.X;
  53. }
  54. set
  55. {
  56. if (value >= sheetSize.X * sheetSize.Y + 1)
  57. {
  58. throw new InvalidOperationException("Specified frame index exceeds available frames");
  59. }
  60. currentFrame.Y = value / sheetSize.X;
  61. currentFrame.X = value % sheetSize.X;
  62. }
  63. }
  64. public bool IsActive { get; private set; }
  65. #endregion
  66. #region Initialization
  67. /// <summary>
  68. /// Creates a new instance of the animation class
  69. /// </summary>
  70. /// <param name="frameSheet">Texture which is a sheet containing
  71. /// the animation frames.</param>
  72. /// <param name="size">The size of a single frame.</param>
  73. /// <param name="frameSheetSize">The size of the entire animation sheet.</param>
  74. public ScaledAnimation(Texture2D frameSheet, Point size, Point frameSheetSize)
  75. {
  76. animatedCharacter = frameSheet;
  77. frameSize = size;
  78. sheetSize = frameSheetSize;
  79. Offset = Vector2.Zero;
  80. }
  81. #endregion
  82. #region Update and Render
  83. /// <summary>
  84. /// Updates the animation's progress.
  85. /// </summary>
  86. /// <param name="gameTime">Game time information.</param>
  87. /// <param name="isInMotion">Whether or not the animation element itself is
  88. /// currently in motion.</param>
  89. public void Update(GameTime gameTime, bool isInMotion)
  90. {
  91. Update(gameTime, isInMotion, false);
  92. }
  93. /// <summary>
  94. /// Updates the animation's progress.
  95. /// </summary>
  96. /// <param name="gameTime">Game time information.</param>
  97. /// <param name="isInMotion">Whether or not the animation element itself is
  98. /// currently in motion.</param>
  99. /// <param name="runSubAnimation"></param>
  100. public void Update(GameTime gameTime, bool isInMotion, bool runSubAnimation)
  101. {
  102. if (IsActive && gameTime.TotalGameTime != lastestChangeTime)
  103. {
  104. // See if a time interval between frames is defined
  105. if (timeInterval != TimeSpan.Zero)
  106. {
  107. // Do nothing until an interval passes
  108. if (lastestChangeTime + timeInterval > gameTime.TotalGameTime)
  109. {
  110. return;
  111. }
  112. }
  113. lastestChangeTime = gameTime.TotalGameTime;
  114. if (FrameIndex >= FrameCount)
  115. {
  116. FrameIndex = 0; // Reset the animation
  117. }
  118. else
  119. {
  120. // Only advance the animation if the animation element is moving
  121. if (isInMotion)
  122. {
  123. if (runSubAnimation)
  124. {
  125. // Initialize the animation
  126. if (lastSubFrame == -1)
  127. {
  128. lastSubFrame = startFrame;
  129. }
  130. // Calculate the currentFrame, which depends on the current
  131. // frame in the parent animation
  132. currentFrame.Y = lastSubFrame / sheetSize.X;
  133. currentFrame.X = lastSubFrame % sheetSize.X;
  134. // Move to the next Frame
  135. lastSubFrame += 1;
  136. // Loop the animation
  137. if (lastSubFrame > endFrame)
  138. {
  139. lastSubFrame = startFrame;
  140. }
  141. }
  142. else
  143. {
  144. // Do not advance frames before the first draw operation
  145. if (drawWasAlreadyCalledOnce)
  146. {
  147. currentFrame.X++;
  148. if (currentFrame.X >= sheetSize.X)
  149. {
  150. currentFrame.X = 0;
  151. currentFrame.Y++;
  152. }
  153. if (currentFrame.Y >= sheetSize.Y)
  154. currentFrame.Y = 0;
  155. if (lastSubFrame != -1)
  156. {
  157. lastSubFrame = -1;
  158. }
  159. }
  160. }
  161. }
  162. }
  163. }
  164. }
  165. /// <summary>
  166. /// Render the animation.
  167. /// </summary>
  168. /// <param name="ScaledSpriteBatch">ScaledSpriteBatch with which the current
  169. /// frame will be rendered.</param>
  170. /// <param name="position">The position to draw the current frame.</param>
  171. /// <param name="spriteEffect">SpriteEffect to apply to the
  172. /// current frame.</param>
  173. public void Draw(ScaledSpriteBatch ScaledSpriteBatch, Vector2 position, SpriteEffects spriteEffect)
  174. {
  175. Draw(ScaledSpriteBatch, position, 1.0f, spriteEffect);
  176. }
  177. /// <summary>
  178. /// Render the animation.
  179. /// </summary>
  180. /// <param name="ScaledSpriteBatch">ScaledSpriteBatch with which the current frame
  181. /// will be rendered.</param>
  182. /// <param name="position">The position to draw the current frame.</param>
  183. /// <param name="scale">Scale factor to apply to the current frame.</param>
  184. /// <param name="spriteEffect">SpriteEffect to apply to the
  185. /// current frame.</param>
  186. public void Draw(ScaledSpriteBatch ScaledSpriteBatch, Vector2 position, float scale, SpriteEffects spriteEffect)
  187. {
  188. drawWasAlreadyCalledOnce = true;
  189. ScaledSpriteBatch.Draw(animatedCharacter, position + Offset,
  190. new Rectangle(frameSize.X * currentFrame.X, frameSize.Y * currentFrame.Y, frameSize.X, frameSize.Y),
  191. Color.White, 0f, Vector2.Zero, scale, spriteEffect, 0);
  192. }
  193. /// <summary>
  194. /// Causes the animation to start playing from a specified frame index.
  195. /// </summary>
  196. /// <param name="frameIndex">Frame index to play the animation from.</param>
  197. public void PlayFromFrameIndex(int frameIndex)
  198. {
  199. FrameIndex = frameIndex;
  200. IsActive = true;
  201. drawWasAlreadyCalledOnce = false;
  202. }
  203. /// <summary>
  204. /// Sets the range of frames which serves as the sub animation.
  205. /// </summary>
  206. /// <param name="startFrame">Start frame for the sub-animation.</param>
  207. /// <param name="endFrame">End frame for the sub-animation.</param>
  208. public void SetSubAnimation(int startFrame, int endFrame)
  209. {
  210. this.startFrame = startFrame;
  211. this.endFrame = endFrame;
  212. }
  213. /// <summary>
  214. /// Used to set the interval between frames.
  215. /// </summary>
  216. /// <param name="interval">The interval between frames.</param>
  217. public void SetFrameInterval(TimeSpan interval)
  218. {
  219. timeInterval = interval;
  220. }
  221. #endregion
  222. }
  223. }