/Src/ClashEngine.NET/Graphics/Objects/Sprite.cs

https://github.com/Fiolek-/Kingdoms-Clash.NET · C# · 233 lines · 162 code · 23 blank · 48 comment · 10 complexity · bfc9aeb3908d328c3053e64281eccfdc MD5 · raw file

  1. using OpenTK;
  2. using System.Text.RegularExpressions;
  3. namespace ClashEngine.NET.Graphics.Objects
  4. {
  5. using Interfaces.Graphics.Objects;
  6. using Interfaces.Graphics.Resources;
  7. /// <summary>
  8. /// Obiekt renderera - duszek.
  9. /// </summary>
  10. /// <remarks>
  11. /// Dzięki przysłonięciu właściwości Texture możemy bez przeszkód wykorzystać Quad jako bazę dla duszka.
  12. /// </remarks>
  13. public class Sprite
  14. : Quad, ISprite
  15. {
  16. #region Private fields
  17. private static Regex AnimationInfoRegex = new Regex(@"(\d+),(\d+)x(\d+),(\d+[\.]?\d*)", RegexOptions.Compiled);
  18. private ITexture _Texture = null;
  19. private SpriteEffect _Effect = SpriteEffect.No;
  20. private bool _MaintainAspectRation = false;
  21. private Vector2 _FrameSize = Vector2.Zero;
  22. private Vector2 _FrameSizePixels = Vector2.Zero;
  23. private uint _CurrentFrame = 0;
  24. private float FrameTimeAggregator = 0.0f;
  25. #endregion
  26. #region ISprite Members
  27. /// <summary>
  28. /// Efekty.
  29. /// </summary>
  30. public SpriteEffect Effect
  31. {
  32. get { return this._Effect; }
  33. set
  34. {
  35. this._Effect = value;
  36. this.UpdateTexCoords();
  37. }
  38. }
  39. /// <summary>
  40. /// Wymusza zachowanie proporcji duszka.
  41. /// </summary>
  42. public bool MaintainAspectRatio
  43. {
  44. get { return this._MaintainAspectRation; }
  45. set
  46. {
  47. this._MaintainAspectRation = true;
  48. this.Size = this.Size;
  49. }
  50. }
  51. /// <summary>
  52. /// Liczba klatek animacji na sprite.
  53. /// </summary>
  54. public uint FramesCount { get; private set; }
  55. /// <summary>
  56. /// Czas trwania jednej klatki.
  57. /// </summary>
  58. public float FrameTime { get; private set; }
  59. /// <summary>
  60. /// Aktualna klatka.
  61. /// </summary>
  62. public uint CurrentFrame
  63. {
  64. get { return this._CurrentFrame; }
  65. set
  66. {
  67. while (value >= this.FramesCount)
  68. value -= this.FramesCount;
  69. this._CurrentFrame = value;
  70. this.UpdateTexCoords();
  71. }
  72. }
  73. /// <summary>
  74. /// Rozmiar klatki.
  75. /// </summary>
  76. public Vector2 FrameSize
  77. {
  78. get { return this._FrameSizePixels; }
  79. }
  80. /// <summary>
  81. /// Przesuwa animacje.
  82. /// </summary>
  83. /// <param name="time">Czas w sekundach.</param>
  84. public void AdvanceAnimation(double time)
  85. {
  86. this.FrameTimeAggregator += (float)time;
  87. if (this.FrameTimeAggregator > this.FrameTime && this.FramesCount > 1)
  88. {
  89. this.CurrentFrame++;
  90. this.FrameTimeAggregator -= this.FrameTime;
  91. }
  92. }
  93. #endregion
  94. #region IObject Members
  95. /// <summary>
  96. /// Tekstura obiektu.
  97. /// </summary>
  98. public new ITexture Texture
  99. {
  100. get { return this._Texture; }
  101. private set
  102. {
  103. this._Texture = value;
  104. this.UpdateTexture();
  105. this.UpdateTexCoords();
  106. }
  107. }
  108. /// <summary>
  109. /// Rozmiar duszka.
  110. /// </summary>
  111. public new Vector2 Size
  112. {
  113. get { return base.Size; }
  114. set { base.Size = (this._MaintainAspectRation ? value * System.Math.Min(value.X / this.Texture.Size.X, value.Y / this.Texture.Size.Y) : value); }
  115. }
  116. #endregion
  117. #region Constructors
  118. /// <summary>
  119. /// Inicjalizuje obiekt.
  120. /// </summary>
  121. /// <param name="texture">Tekstura.</param>
  122. /// <param name="position">Pozycja.</param>
  123. /// <param name="effect">Efekt.</param>
  124. public Sprite(ITexture texture, Vector2 position)
  125. : base(position, texture.Size, Vector4.One)
  126. {
  127. this.Texture = texture;
  128. this.Depth = 0f;
  129. }
  130. /// <summary>
  131. /// Inicjalizuje obiekt.
  132. /// </summary>
  133. /// <param name="texture">Tekstura.</param>
  134. /// <param name="position">Pozycja.</param>
  135. /// <param name="size">Rozmiar.</param>
  136. /// <param name="effect">Efekt.</param>
  137. public Sprite(ITexture texture, Vector2 position, Vector2 size)
  138. : base(position, size, Vector4.One)
  139. {
  140. this.Texture = texture;
  141. }
  142. #endregion
  143. #region Private methods
  144. private void UpdateTexCoords()
  145. {
  146. float l = this.Texture.Coordinates.Left + this._FrameSize.X * this.CurrentFrame,
  147. r = this.Texture.Coordinates.Left + this._FrameSize.X * (this.CurrentFrame + 1),
  148. t = this.Texture.Coordinates.Top,
  149. b = this.Texture.Coordinates.Top + this._FrameSize.Y;
  150. float left, right;
  151. float top, bottom;
  152. if ((this.Effect & SpriteEffect.FlipHorizontally) == SpriteEffect.FlipHorizontally)
  153. {
  154. left = r;
  155. right = l;
  156. }
  157. else
  158. {
  159. right = r;
  160. left = l;
  161. }
  162. if ((this.Effect & SpriteEffect.FlipVertically) == SpriteEffect.FlipVertically)
  163. {
  164. top = b;
  165. bottom = t;
  166. }
  167. else
  168. {
  169. bottom = b;
  170. top = t;
  171. }
  172. this.Vertices[0].TexCoord = new Vector2(left, top);
  173. this.Vertices[1].TexCoord = new Vector2(right, top);
  174. this.Vertices[2].TexCoord = new Vector2(right, bottom);
  175. this.Vertices[3].TexCoord = new Vector2(left, bottom);
  176. }
  177. private void UpdateTexture()
  178. {
  179. //Ustawiamy na domyślne.
  180. this.FramesCount = 1;
  181. this.FrameTime = 1f;
  182. this.CurrentFrame = 0;
  183. this._FrameSize = Vector2.One;
  184. this._FrameSizePixels = Vector2.Zero;
  185. if (this.Texture != null)
  186. {
  187. this._FrameSizePixels = this.Texture.Size;
  188. var match = AnimationInfoRegex.Match(this.Texture.UserData);
  189. if (match.Success) //Mamy informacje o animacji
  190. {
  191. try
  192. {
  193. uint frames = uint.Parse(match.Groups[1].Value);
  194. Vector2 frameSize = new Vector2((float)uint.Parse(match.Groups[2].Value), (float)uint.Parse(match.Groups[3].Value));
  195. float framesTime = float.Parse(match.Groups[4].Value, System.Globalization.CultureInfo.InvariantCulture);
  196. this.FramesCount = frames;
  197. this.FrameTime = framesTime / frames;
  198. this._FrameSizePixels = frameSize;
  199. this._FrameSize.X = frameSize.X / this.Texture.Size.X;
  200. this._FrameSize.Y = frameSize.Y / this.Texture.Size.Y;
  201. this.CurrentFrame = 0;
  202. }
  203. catch
  204. { }
  205. }
  206. }
  207. }
  208. #endregion
  209. }
  210. }