1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using Microsoft.Xna.Framework.Graphics;
5 using Microsoft.Xna.Framework;
6
7 namespace BrawlerGame
8 {
9 public class SpriteAnimation
10 {
11 #region Declarations
12 // The texture that holds the images for this sprite
13 Texture2D t2dTexture;
14
15 // True if animations are being played
16 bool bAnimating = true;
17 bool allowMove = true;
18
19 // If set to anything other than Color.White, will colorize
20 // the sprite with that color.
21 Color colorTint = Color.White;
22
23 // Screen Position of the Sprite
24 Vector2 v2Position = new Vector2(0, 0);
25 Vector2 v2LastPosition = new Vector2(0, 0);
26
27 // Dictionary holding all of the FrameAnimation objects
28 // associated with this sprite.
29 Dictionary<string, FrameAnimation> faAnimations = new Dictionary<string, FrameAnimation>();
30
31 // Which FrameAnimation from the dictionary above is playing
32 string sCurrentAnimation = null;
33
34 // If true, the sprite will automatically rotate to align itself
35 // with the angle difference between it's new position and
36 // it's previous position. In this case, the 0 rotation point
37 // is to the right (so the sprite should start out facing to
38 // the right.
39 bool bRotateByPosition = false;
40
41 // How much the sprite should be rotated by when drawn
42 // Value is in Radians, and 0 indicates no rotation.
43 float fRotation = 0f;
44
45 // Calcualted center of the sprite
46 Vector2 v2Center;
47
48 // Calculated width and height of the sprite
49 int iWidth;
50 int iHeight;
51
52 // Scale of Sprite
53 float fScale = 1f;
54
55 // Flip image
56 byte flipImage = 0;
57
58 // Used to add damage to entity at the END of the animation
59 public bool bDamage = false;
60 #endregion
61
62
63 #region Properties
64 /// <summary>
65 /// Vector2 representing the position of the sprite's upper left
66 /// corner pixel.
67 /// </summary>
68 public Vector2 Position
69 {
70 get { return v2Position; }
71 set
72 {
73 v2LastPosition = v2Position;
74 v2Position = value;
75 UpdateRotation();
76 }
77 }
78
79 /// <summary>
80 /// The X position of the sprite's upper left corner pixel.
81 /// </summary>
82 public float PositionX
83 {
84 get { return v2Position.X; }
85 set
86 {
87 v2LastPosition.X = v2Position.X;
88 v2Position.X = value;
89 UpdateRotation();
90 }
91 }
92
93 /// <summary>
94 /// The Y position of the sprite's upper left corner pixel.
95 /// </summary>
96 public float PositionY
97 {
98 get { return v2Position.Y; }
99 set
100 {
101 v2LastPosition.Y = v2Position.Y;
102 v2Position.Y = value;
103 UpdateRotation();
104 }
105 }
106
107 /// <summary>
108 /// The X position of the sprite's upper left corner pixel.
109 /// </summary>
110 public int X
111 {
112 get { return (int)v2Position.X; }
113 set
114 {
115 v2LastPosition.X = v2Position.X;
116 v2Position.X = value;
117 UpdateRotation();
118 }
119 }
120
121 /// <summary>
122 /// The Y position of the sprite's upper left corner pixel.
123 /// </summary>
124 public int Y
125 {
126 get { return (int)v2Position.Y; }
127 set
128 {
129 v2LastPosition.Y = v2Position.Y;
130 v2Position.Y = value;
131 UpdateRotation();
132 }
133 }
134
135 /// <summary>
136 /// Width (in pixels) of the sprite animation frames
137 /// </summary>
138 public int Width
139 {
140 get { return iWidth; }
141 }
142
143 /// <summary>
144 /// Height (in pixels) of the sprite animation frames
145 /// </summary>
146 public int Height
147 {
148 get { return iHeight; }
149 }
150
151
152 /// <summary>
153 /// If true, the sprite will automatically rotate in the direction
154 /// of motion whenever the sprite's Position changes.
155 /// </summary>
156 public bool AutoRotate
157 {
158 get { return bRotateByPosition; }
159 set { bRotateByPosition = value; }
160 }
161
162 /// <summary>
163 /// The degree of rotation (in radians) to be applied to the
164 /// sprite when drawn.
165 /// </summary>
166 public float Rotation
167 {
168 get { return fRotation; }
169 set { fRotation = value; }
170 }
171
172 /// <summary>
173 /// Screen coordinates of the bounding box surrounding this sprite
174 /// </summary>
175 public Rectangle BoundingBox
176 {
177 get { return new Rectangle(X, Y, iWidth, iHeight); }
178 }
179
180
181 /// <summary>
182 /// The texture associated with this sprite. All FrameAnimations will be
183 /// relative to this texture.
184 /// </summary>
185 public Texture2D Texture
186 {
187 get { return t2dTexture; }
188 }
189
190 /// <summary>
191 /// Color value to tint the sprite with when drawing. Color.White
192 /// (the default) indicates no tinting.
193 /// </summary>
194 public Color Tint
195 {
196 get { return colorTint; }
197 set { colorTint = value; }
198 }
199
200 /// <summary>
201 /// Scale of sprite
202 /// </summary>
203 public float Scale
204 {
205 get { return fScale; }
206 set { fScale = value; }
207 }
208
209 /// <summary>
210 /// Determined to flip image
211 /// </summary>
212 public byte IsFlipped
213 {
214 get { return flipImage; }
215 set { flipImage = value; }
216 }
217
218 /// <summary>
219 /// True if the sprite is (or should be) playing animation frames. If this value is set
220 /// to false, the sprite will not be drawn (a sprite needs at least 1 single frame animation
221 /// in order to be displayed.
222 /// </summary>
223 public bool IsAnimating
224 {
225 get { return bAnimating; }
226 set { bAnimating = value; }
227 }
228
229 public bool CanMove
230 {
231 get { return allowMove; }
232 set { allowMove = value; }
233 }
234
235 /// <summary>
236 /// The FrameAnimation object of the currently playing animation
237 /// </summary>
238 public FrameAnimation CurrentFrameAnimation
239 {
240 get
241 {
242 if (!string.IsNullOrEmpty(sCurrentAnimation))
243 return faAnimations[sCurrentAnimation];
244 else
245 return null;
246 }
247 }
248
249 /// <summary>
250 /// The string name of the currently playing animaton. Setting the animation
251 /// resets the CurrentFrame and PlayCount properties to zero.
252 /// </summary>
253 public string CurrentAnimation
254 {
255 get { return sCurrentAnimation; }
256 set
257 {
258 if (faAnimations.ContainsKey(value))
259 {
260 sCurrentAnimation = value;
261 faAnimations[sCurrentAnimation].CurrentFrame = 0;
262 faAnimations[sCurrentAnimation].PlayCount = 0;
263 }
264 }
265 }
266 #endregion
267
268
269 #region Constructors
270 public SpriteAnimation(Texture2D Texture)
271 {
272 t2dTexture = Texture;
273 }
274 #endregion
275
276
277 #region Methods
278 /// <summary>
279 /// Updates the rotation of the sprite based on it's "last known" position
280 /// if the "bRotatebyPosition" parameter is true.
281 /// </summary>
282 void UpdateRotation()
283 {
284 if (bRotateByPosition)
285 {
286 if (IsFlipped == 0)
287 {
288 flipImage = 0;
289 }
290 else
291 flipImage = 1;
292 }
293 }
294
295 /// <summary>
296 /// Add an animation to the animations dictionary.
297 /// </summary>
298 /// <param name="Name">Sprite-specific name of the animation.</param>
299 /// <param name="X">X Location of the upper right corner of the first frame of the animation</param>
300 /// <param name="Y">Y Location of the upper right corner of the first frame of the animation</param>
301 /// <param name="Width">Width of the animation's frames</param>
302 /// <param name="Height">Height of the animation's frames</param>
303 /// <param name="Frames">Number of frames in the animation</param>
304 /// <param name="FrameLength">Length (in seconds) to display each frame of the animation</param>
305 public void AddAnimation(string Name, int X, int Y, int Width, int Height, int Frames, float FrameLength)
306 {
307 faAnimations.Add(Name, new FrameAnimation(X, Y, Width, Height, Frames, FrameLength));
308 iWidth = Width;
309 iHeight = Height;
310 v2Center = new Vector2(iWidth / 2, iHeight / 2);
311 }
312
313 /// <summary>
314 /// Add an animation to the animations dictionary.
315 /// </summary>
316 /// <param name="Name">Sprite-specific name of the animation.</param>
317 /// <param name="X">X Location of the upper right corner of the first frame of the animation</param>
318 /// <param name="Y">Y Location of the upper right corner of the first frame of the animation</param>
319 /// <param name="Width">Width of the animation's frames</param>
320 /// <param name="Height">Height of the animation's frames</param>
321 /// <param name="Frames">Number of frames in the animation</param>
322 /// <param name="NextAnimation">Name of the animation to play after this animation ends</param>
323 public void AddAnimation(string Name, int X, int Y, int Width, int Height, int Frames, float FrameLength, string NextAnimation)
324 {
325 faAnimations.Add(Name, new FrameAnimation(X, Y, Width, Height, Frames, FrameLength, NextAnimation));
326 iWidth = Width;
327 iHeight = Height;
328 v2Center = new Vector2(iWidth / 2, iHeight / 2);
329 }
330
331 /// <summary>
332 /// Returns a FrameAnimation object associated with this sprite via
333 /// the animation name.
334 /// </summary>
335 /// <param name="Name"></param>
336 /// <returns></returns>
337 public FrameAnimation GetAnimationByName(string Name)
338 {
339 if (faAnimations.ContainsKey(Name))
340 {
341 return faAnimations[Name];
342 }
343 else
344 {
345 return null;
346 }
347 }
348
349 public void MoveBy(float x, float y)
350 {
351 v2LastPosition = v2Position;
352 v2Position.X += x;
353 v2Position.Y += y;
354 UpdateRotation();
355 }
356 #endregion
357
358
359 #region Update
360 public void Update(GameTime gameTime)
361 {
362 if (bAnimating)
363 {
364 // If there is not a currently active animation
365 if (CurrentFrameAnimation == null)
366 {
367 // Make sure we have an animation associated with this sprite
368 if (faAnimations.Count > 0)
369 {
370 // Set the active animation to the first animation
371 // associated with this sprite
372 string[] sKeys = new string[faAnimations.Count];
373 faAnimations.Keys.CopyTo(sKeys, 0);
374 CurrentAnimation = sKeys[0];
375 }
376 else
377 {
378 return;
379 }
380 }
381
382 if (CurrentFrameAnimation.PlayCount > 0)
383 {
384 // Update damge
385 bDamage = true;
386
387 // Check to see if there is a "followup" animation named for this animation
388 if (!String.IsNullOrEmpty(CurrentFrameAnimation.NextAnimation))
389 {
390 // If it has, set up the next animation
391 CurrentAnimation = CurrentFrameAnimation.NextAnimation;
392 }
393 string[] sKeys = new string[faAnimations.Count];
394 faAnimations.Keys.CopyTo(sKeys, 0);
395 CurrentAnimation = sKeys[0];
396 }
397 else
398 bDamage = false;
399
400 CurrentFrameAnimation.Update(gameTime);
401 }
402 }
403 #endregion
404
405
406 #region Draw
407 public void Draw(SpriteBatch spriteBatch, int XOffset, int YOffset)
408 {
409 if (bAnimating)
410 {
411 SpriteEffects spriteEffect = SpriteEffects.None;
412 if (flipImage == 1)
413 {
414 spriteEffect = SpriteEffects.FlipHorizontally;
415 }
416 spriteBatch.Draw(t2dTexture, (v2Position + new Vector2(XOffset, YOffset) + v2Center),
417 CurrentFrameAnimation.FrameRectangle, colorTint,
418 fRotation, v2Center, fScale, spriteEffect, 0);
419 }
420 }
421 #endregion
422
423 }
424 }