Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
SpriteAnimationSystem.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System.Collections.Generic;
4 
5 using SiliconStudio.Core;
6 using SiliconStudio.Paradox.DataModel;
7 using SiliconStudio.Paradox.Games;
8 
9 namespace SiliconStudio.Paradox.Engine
10 {
11  /// <summary>
12  /// A system in charge of animating the sprites
13  /// </summary>
15  {
16  private readonly HashSet<SpriteComponent> playingSprites = new HashSet<SpriteComponent>();
17  private readonly HashSet<SpriteComponent> spritesToStop = new HashSet<SpriteComponent>();
18 
19  /// <summary>
20  /// Gets or sets the default sprite animation FPS (Default value = 30 FPS).
21  /// </summary>
22  public float DefaultFramesPerSecond { get; set; }
23 
24  /// <summary>
25  /// Creates a new instance of <see cref="SpriteAnimationSystem"/> and register it in the services.
26  /// </summary>
27  /// <param name="registry"></param>
29  : base(registry)
30  {
31  registry.AddService(typeof(SpriteAnimationSystem), this);
32 
33  DefaultFramesPerSecond = 30;
34  }
35 
36  public override void Initialize()
37  {
38  base.Initialize();
39 
40  Visible = true;
41  }
42 
43  public override void Draw(GameTime gameTime)
44  {
45  base.Draw(gameTime);
46 
47  var elapsedTime = gameTime.Elapsed.TotalSeconds;
48 
49  foreach (var sprite in playingSprites)
50  {
51  if(sprite.IsPaused)
52  continue;
53 
54  sprite.ElapsedTime += elapsedTime;
55 
56  // As long as we have some animations to play for the given sprite...
57  while (sprite.Animations.Count > 0)
58  {
59  var animationInfo = sprite.Animations.Peek();
60  var oneFrameTime = 1 / animationInfo.FramePerSeconds;
61 
62  // As long as needed and possible go to the next animation frame
63  while (sprite.ElapsedTime >= oneFrameTime && (animationInfo.ShouldLoop || sprite.CurrentIndexIndex < animationInfo.SpriteIndices.Count-1))
64  {
65  sprite.ElapsedTime -= oneFrameTime;
66  sprite.CurrentIndexIndex = (sprite.CurrentIndexIndex + 1) % animationInfo.SpriteIndices.Count;
67  }
68 
69  // set the sprite frame
70  sprite.CurrentFrame = animationInfo.SpriteIndices[sprite.CurrentIndexIndex];
71 
72  // we reached the end of the animation -> go to next animation
73  if (sprite.ElapsedTime >= oneFrameTime)
74  {
75  sprite.ElapsedTime -= oneFrameTime; // consider that one frame elapse between the two animations
76  sprite.RecycleFirstAnimation();
77  }
78  else // animation is not finished yet -> exit loop
79  {
80  break;
81  }
82  }
83 
84  // There is no more animations to play for this sprite -> remove it from the sprite to animate list
85  if (sprite.Animations.Count == 0)
86  spritesToStop.Add(sprite);
87  }
88 
89  // actually stops the sprites that have finished their animation
90  foreach (var spriteComponent in spritesToStop)
91  {
92  playingSprites.Remove(spriteComponent);
93  spriteComponent.CurrentIndexIndex = 0;
94  spriteComponent.ElapsedTime = 0;
95  }
96  spritesToStop.Clear();
97  }
98 
99  /// <summary>
100  /// Play the sprite animation starting at index <paramref name="startIndex"/> and ending at <paramref name="endIndex"/>.
101  /// </summary>
102  /// <param name="spriteComponent">The sprite component containing the animation</param>
103  /// <param name="startIndex">The first index of the animation</param>
104  /// <param name="endIndex">The last index of the animation</param>
105  /// <param name="repeatMode">The value indicating how to loop the animation</param>
106  /// <param name="framesPerSeconds">The animation speed in frames per second. 0 to use the sprite animation system default speed.</param>
107  /// <param name="clearQueuedAnimations">Indicate if queued animation should be cleared</param>
108  public void Play(SpriteComponent spriteComponent, int startIndex, int endIndex, AnimationRepeatMode repeatMode, float framesPerSeconds = 0, bool clearQueuedAnimations = true)
109  {
110  if(spriteComponent == null)
111  return;
112 
113  var animationInfo = new SpriteComponent.AnimationInfo
114  {
115  ShouldLoop = repeatMode == AnimationRepeatMode.LoopInfinite,
116  SpriteIndices = SpriteComponent.GetNewSpriteIndicesList(),
117  FramePerSeconds = framesPerSeconds > 0 ? framesPerSeconds : DefaultFramesPerSecond,
118  };
119 
120  for (int i = startIndex; i <= endIndex; i++)
121  animationInfo.SpriteIndices.Add(i);
122 
123  spriteComponent.RecycleFirstAnimation();
124  spriteComponent.Animations.Enqueue(animationInfo);
125  var queuedAnimationsCount = spriteComponent.Animations.Count - 1;
126  for (int i = 0; i < queuedAnimationsCount; i++)
127  {
128  var queuedAnimation = spriteComponent.Animations.Dequeue();
129  if(!clearQueuedAnimations)
130  spriteComponent.Animations.Enqueue(queuedAnimation);
131  }
132 
133  playingSprites.Add(spriteComponent);
134  spriteComponent.ElapsedTime = 0;
135  spriteComponent.CurrentIndexIndex = 0;
136  spriteComponent.IsPaused = false;
137  }
138 
139  /// <summary>
140  /// Play the sprite animation defined by the provided sequence of indices.
141  /// </summary>
142  /// <param name="spriteComponent">The sprite component containing the animation</param>
143  /// <param name="indices">The sequence of indices defining the sprite animation</param>
144  /// <param name="repeatMode">The value indicating how to loop the animation</param>
145  /// <param name="framesPerSeconds">The animation speed in frames per second. 0 to use the sprite animation system default speed.</param>
146  /// <param name="clearQueuedAnimations">Indicate if queued animation should be cleared</param>
147  public void Play(SpriteComponent spriteComponent, int[] indices, AnimationRepeatMode repeatMode, float framesPerSeconds = 0, bool clearQueuedAnimations = true)
148  {
149  if (spriteComponent == null)
150  return;
151 
152  var animationInfo = new SpriteComponent.AnimationInfo
153  {
154  ShouldLoop = repeatMode == AnimationRepeatMode.LoopInfinite,
155  SpriteIndices = SpriteComponent.GetNewSpriteIndicesList(),
156  FramePerSeconds = framesPerSeconds > 0 ? framesPerSeconds : DefaultFramesPerSecond,
157  };
158 
159  foreach (var i in indices)
160  animationInfo.SpriteIndices.Add(i);
161 
162  spriteComponent.RecycleFirstAnimation();
163  spriteComponent.Animations.Enqueue(animationInfo);
164  var queuedAnimationsCount = spriteComponent.Animations.Count - 1;
165  for (int i = 0; i < queuedAnimationsCount; i++)
166  {
167  var queuedAnimation = spriteComponent.Animations.Dequeue();
168  if (!clearQueuedAnimations)
169  spriteComponent.Animations.Enqueue(queuedAnimation);
170  }
171 
172  playingSprites.Add(spriteComponent);
173  spriteComponent.ElapsedTime = 0;
174  spriteComponent.CurrentIndexIndex = 0;
175  spriteComponent.IsPaused = false;
176  }
177 
178  /// <summary>
179  /// Queue the sprite animation starting at index <paramref name="startIndex"/> and ending at <paramref name="endIndex"/> at the end of the animation queue.
180  /// </summary>
181  /// <param name="spriteComponent">The sprite component containing the animation</param>
182  /// <param name="startIndex">The first index of the animation</param>
183  /// <param name="endIndex">The last index of the animation</param>
184  /// <param name="repeatMode">The value indicating how to loop the animation</param>
185  /// <param name="framesPerSeconds">The animation speed in frames per second. 0 to use the sprite animation system default speed.</param>
186  public void Queue(SpriteComponent spriteComponent, int startIndex, int endIndex, AnimationRepeatMode repeatMode, float framesPerSeconds = 0)
187  {
188  if (spriteComponent == null)
189  return;
190 
191  var animationInfo = new SpriteComponent.AnimationInfo
192  {
193  ShouldLoop = repeatMode == AnimationRepeatMode.LoopInfinite,
194  FramePerSeconds = framesPerSeconds > 0 ? framesPerSeconds : DefaultFramesPerSecond,
195  SpriteIndices = SpriteComponent.GetNewSpriteIndicesList()
196  };
197 
198  for (int i = startIndex; i <= endIndex; i++)
199  animationInfo.SpriteIndices.Add(i);
200 
201  spriteComponent.Animations.Enqueue(animationInfo);
202 
203  playingSprites.Add(spriteComponent);
204  }
205 
206  /// <summary>
207  /// Queue the sprite animation defined by the provided sequence of indices at the end of the animation queue.
208  /// </summary>
209  /// <param name="spriteComponent">The sprite component containing the animation</param>
210  /// <param name="indices">The sequence of indices defining the sprite animation</param>
211  /// <param name="repeatMode">The value indicating how to loop the animation</param>
212  /// <param name="framesPerSeconds">The animation speed in frames per second. 0 to use the sprite animation system default speed.</param>
213  public void Queue(SpriteComponent spriteComponent, int[] indices, AnimationRepeatMode repeatMode, float framesPerSeconds = 0)
214  {
215  if (spriteComponent == null)
216  return;
217 
218  var animationInfo = new SpriteComponent.AnimationInfo
219  {
220  ShouldLoop = repeatMode == AnimationRepeatMode.LoopInfinite,
221  FramePerSeconds = framesPerSeconds > 0 ? framesPerSeconds : DefaultFramesPerSecond,
222  SpriteIndices = SpriteComponent.GetNewSpriteIndicesList()
223  };
224 
225  foreach(var i in indices)
226  animationInfo.SpriteIndices.Add(i);
227 
228  spriteComponent.Animations.Enqueue(animationInfo);
229 
230  playingSprites.Add(spriteComponent);
231  }
232 
233  /// <summary>
234  /// Pauses the animation of the provided sprite component.
235  /// </summary>
236  /// <param name="spriteComponent">the sprite component to pause</param>
237  public void Pause(SpriteComponent spriteComponent)
238  {
239  spriteComponent.IsPaused = true;
240  }
241 
242  /// <summary>
243  /// Resumes a previously paused animation.
244  /// </summary>
245  /// <param name="spriteComponent">the sprite component to resume</param>
246  public void Resume(SpriteComponent spriteComponent)
247  {
248  spriteComponent.IsPaused = false;
249  }
250 
251  /// <summary>
252  /// Stops the animation of the provided sprite component.
253  /// </summary>
254  /// <param name="spriteComponent">the sprite component to stop</param>
255  public void Stop(SpriteComponent spriteComponent)
256  {
257  spriteComponent.ElapsedTime = 0;
258  spriteComponent.CurrentIndexIndex = 0;
259  spriteComponent.ClearAnimations();
260  playingSprites.Remove(spriteComponent);
261  }
262  }
263 }
void Stop(SpriteComponent spriteComponent)
Stops the animation of the provided sprite component.
A system in charge of animating the sprites
override void Draw(GameTime gameTime)
Draws this instance.
void Queue(SpriteComponent spriteComponent, int[] indices, AnimationRepeatMode repeatMode, float framesPerSeconds=0)
Queue the sprite animation defined by the provided sequence of indices at the end of the animation qu...
void Play(SpriteComponent spriteComponent, int startIndex, int endIndex, AnimationRepeatMode repeatMode, float framesPerSeconds=0, bool clearQueuedAnimations=true)
Play the sprite animation starting at index startIndex and ending at endIndex .
A service registry is a IServiceProvider that provides methods to register and unregister services...
SpriteAnimationSystem(IServiceRegistry registry)
Creates a new instance of SpriteAnimationSystem and register it in the services.
void Queue(SpriteComponent spriteComponent, int startIndex, int endIndex, AnimationRepeatMode repeatMode, float framesPerSeconds=0)
Queue the sprite animation starting at index startIndex and ending at endIndex at the end of the an...
Add a Sprite to an Entity. It could be an animated sprite.
AnimationRepeatMode
Enumeration describing how an animation should be repeated.
Current timing used for variable-step (real time) or fixed-step (game time) games.
Definition: GameTime.cs:31
override void Initialize()
This method is called when the component is added to the game.
void Play(SpriteComponent spriteComponent, int[] indices, AnimationRepeatMode repeatMode, float framesPerSeconds=0, bool clearQueuedAnimations=true)
Play the sprite animation defined by the provided sequence of indices.
void Pause(SpriteComponent spriteComponent)
Pauses the animation of the provided sprite component.
void Resume(SpriteComponent spriteComponent)
Resumes a previously paused animation.