Jypeli  5
The simple game programming library
Animation.cs
Siirry tämän tiedoston dokumentaatioon.
1 #region MIT License
2 /*
3  * Copyright (c) 2009 University of Jyväskylä, Department of Mathematical
4  * Information Technology.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #endregion
25 
26 /*
27  * Authors: Tero Jäntti, Tomi Karppinen, Janne Nikkanen.
28  */
29 
30 using System;
31 using System.Collections.Generic;
32 
33 
34 namespace Jypeli
35 {
56  public class Animation : IEnumerable<Image>
57  {
58  private double secondsPerFrame;
59  private TimeSpan startTime;
60  private int currentIndex;
61  private int repeatCount = -1; // When -1, animation repeats forever.
62 
63  // NOTES:
64  //
65  // Animation frames should be immutable, because that is what
66  // the Layer class assumes. So, let's not provide
67  // any methods to modify the images of an existing animation.
68  //
69  // This is not a big deal, as there rarely is any need
70  // to modify animations at runtime and constructing new
71  // animation objects is quite easy anyway.
72 
73 #if !XBOX && !WINDOWS_PHONE
74  [NonSerialized]
75 #endif
76  internal Image[] frames = null;
77 
81  public int FrameCount
82  {
83  get { return frames.Length; }
84  }
85 
86  int lastRepeat = 0;
87 
91  public int CurrentFrameIndex
92  {
93  get
94  {
95  if ( !IsPlaying ) return currentIndex;
96 
97  double secondsNow = Game.Time.SinceStartOfGame.TotalSeconds;
98  double secondsAdvanced = secondsNow - startTime.TotalSeconds;
99  int currentRepeat = (int)( secondsAdvanced / ( FrameCount * secondsPerFrame ) );
100 
101  if ( currentRepeat > lastRepeat )
102  {
103  OnPlayed();
104  lastRepeat = currentRepeat;
105  }
106 
107  if ( repeatCount >= 0 && currentRepeat >= repeatCount )
108  Stop();
109 
110  return ( (int)( secondsAdvanced * FPS ) ) % FrameCount;
111  }
112  }
113 
117  public bool IsPlaying { get; set; }
118 
122  public double FPS
123  {
124  get { return 1 / secondsPerFrame; }
125  set
126  {
127  if ( value == 0 )
128  throw new ArgumentException( "FPS can not be zero" );
129  secondsPerFrame = 1 / value;
130  }
131  }
132 
136  public Image CurrentFrame
137  {
138  get { return frames[CurrentFrameIndex]; }
139  }
140 
145  public bool StopOnLastFrame { get; set; }
146 
150  public double Width
151  {
152  get { return FrameCount > 0 ? frames[0].Width : 0; }
153  }
154 
158  public double Height
159  {
160  get { return FrameCount > 0 ? frames[0].Height : 0; }
161  }
162 
166  public Vector Size
167  {
168  get { return new Vector( Width, Height ); }
169  }
170 
174  public event Action Played;
175 
176  private void OnPlayed()
177  {
178  if ( Played != null ) Played();
179  }
180 
185  public Animation( params Image[] frames )
186  {
187  if ( frames.Length == 0 )
188  throw new ArgumentException( "Animation must have at least one frame." );
189  FPS = 25;
190  currentIndex = 0;
191  startTime = Game.Time.SinceStartOfGame;
192  this.frames = frames;
193  }
194 
199  public static implicit operator Animation(Image image)
200  {
201  if ( image == null ) return null;
202  return new Animation( image );
203  }
204 
209  public Animation( Animation src )
210  {
211  FPS = src.FPS;
212  IsPlaying = src.IsPlaying;
213  startTime = src.startTime;
214  currentIndex = src.currentIndex;
215  repeatCount = src.repeatCount;
216  frames = new Image[src.FrameCount];
217 
218  // Copy only the references to images.
219  for ( int i = 0; i < src.FrameCount; i++ )
220  frames[i] = src.frames[i];
221  }
222 
229  public static Animation Apply( Animation anim, Converter<Image, Image> method )
230  {
231  Animation applied = new Animation( anim );
232 
233  for ( int i = 0; i < anim.frames.Length; i++ )
234  {
235  applied.frames[i] = method(anim.frames[i]);
236  }
237 
238  return applied;
239  }
240 
246  public static Animation Mirror( Animation anim )
247  {
248  return Apply( anim, Image.Mirror );
249  }
250 
256  public static Animation Flip( Animation anim )
257  {
258  return Apply( anim, Image.Flip );
259  }
260 
266  public static Animation Reverse( Animation anim )
267  {
268  Animation reversed = new Animation( anim );
269 
270  for ( int i = 0; i < anim.frames.Length / 2; i++ )
271  {
272  reversed.frames[i] = anim.frames[anim.frames.Length - 1 - i];
273  reversed.frames[anim.frames.Length - 1 - i] = anim.frames[i];
274  }
275 
276  return reversed;
277  }
278 
282  public void Start()
283  {
284  Start( -1 );
285  }
286 
291  public void Start( int repeatCount )
292  {
293  this.repeatCount = repeatCount;
294  startTime = Game.Time.SinceStartOfGame;
295  IsPlaying = true;
296  lastRepeat = 0;
297  }
298 
302  public void Pause()
303  {
304  IsPlaying = false;
305  }
306 
310  public void Resume()
311  {
312  IsPlaying = true;
313  }
314 
318  public void Stop()
319  {
320  IsPlaying = false;
321  currentIndex = 0;
322  if ( StopOnLastFrame )
323  currentIndex = FrameCount - 1;
324  repeatCount = -1;
325  }
326 
332  public void Step( int numberOfFrames )
333  {
334  IsPlaying = false;
335  currentIndex = currentIndex + numberOfFrames;
336 
337  if ( currentIndex >= FrameCount )
338  {
339  // Animation has reached its final frame
340  if ( repeatCount > 0 ) repeatCount--;
341 
342  if ( repeatCount == 0 )
343  Stop();
344  else
345  {
346  // Play it again, Sam
347  currentIndex %= FrameCount;
348  }
349 
350  OnPlayed();
351  }
352  }
353 
357  public void Step()
358  {
359  Step( 1 );
360  }
361 
362  #region IEnumerable<Image> Members
363 
364  public IEnumerator<Image> GetEnumerator()
365  {
366  foreach ( Image frame in frames )
367  yield return frame;
368  }
369 
370  #endregion
371 
372  #region IEnumerable Members
373 
374  System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
375  {
376  return frames.GetEnumerator();
377  }
378 
379  #endregion
380  }
381 }
static Image Mirror(Image image)
Peilaa kuvan X-suunnassa.
Definition: Image.cs:810
bool IsPlaying
Onko animaatio käynnissä.
Definition: Animation.cs:117
void Step()
Etenee animaatiossa yhden ruudun eteenpäin.
Definition: Animation.cs:357
Action Played
Tapahtuma, joka tapahtuu kun animaatio on suoritettu.
Definition: Animation.cs:174
Vector Size
Animaation koko. Vector.Zero, jos animaatiossa ei ole yhtään ruutua.
Definition: Animation.cs:167
static Animation Reverse(Animation anim)
Palauttaa animaation, joka toistuu lopusta alkuun.
Definition: Animation.cs:266
TimeSpan SinceStartOfGame
Aika joka on kulunut pelin alusta.
Definition: Time.cs:32
Image CurrentFrame
Tällä hetkellä näkyvä ruutu animaatiosta.
Definition: Animation.cs:137
void Pause()
Keskeyttää animaation toiston.
Definition: Animation.cs:302
bool StopOnLastFrame
Jos true, animaatio ei pysähtyessä palaa ensimmäiseen ruutuun.
Definition: Animation.cs:145
int Width
Leveys pikseleinä.
Definition: Image.cs:290
static Animation Mirror(Animation anim)
Peilaa animaation X-suunnasssa.
Definition: Animation.cs:246
double FPS
Animaation päivitysnopeus ruutuina sekunnissa (frames per second).
Definition: Animation.cs:123
Kuva.
Definition: Image.cs:24
void Start(int repeatCount)
Käynnistää animaation alusta.
Definition: Animation.cs:291
static Animation Flip(Animation anim)
Peilaa animaation Y-suunnasssa.
Definition: Animation.cs:256
Animation(params Image[] frames)
Luo uuden animaation.
Definition: Animation.cs:185
Peliluokka reaaliaikaisille peleille.
Definition: DebugScreen.cs:10
void Start()
Käynnistää animaation alusta.
Definition: Animation.cs:282
Animation(Animation src)
Luo kopion jo tunnetusta animaatiosta.
Definition: Animation.cs:209
static Animation Apply(Animation anim, Converter< Image, Image > method)
Käyttää haluttua metodia kaikkiin animaation ruutuihin.
Definition: Animation.cs:229
void Stop()
Pysäyttää animaation asettaen sen ensimmäiseen ruutuun.
Definition: Animation.cs:318
void Resume()
Jatkaa animaatiota siitä, mihin viimeksi jäätiin.
Definition: Animation.cs:310
int Height
Korkeus pikseleinä.
Definition: Image.cs:298
int FrameCount
Ruutujen määrä.
Definition: Animation.cs:82
void Step(int numberOfFrames)
Etenee animaatiossa halutun määrän ruutuja. Käytä negatiivisia arvoja, jos haluat kulkea taaksepäin...
Definition: Animation.cs:332
Sarja kuvia, jotka vaihtuvat halutulla nopeudella. Yksi animaatio koostuu yhdestä tai useammasta kuva...
Definition: Animation.cs:56
static Time Time
Peliaika. Sisältää tiedon siitä, kuinka kauan peliä on pelattu (Time.SinceStartOfGame) ja kuinka kaua...
Definition: Game.cs:309
double Width
Animaation leveys. Nolla, jos animaatiossa ei ole yhtään ruutua.
Definition: Animation.cs:151
int CurrentFrameIndex
Aktiivisen animaatioruudun indeksi (alkaa nollasta).
Definition: Animation.cs:92
2D-vektori.
Definition: Vector.cs:56
IEnumerator< Image > GetEnumerator()
Definition: Animation.cs:364
double Height
Animaation korkeus. Nolla, jos animaatiossa ei ole yhtään ruutua.
Definition: Animation.cs:159
static Image Flip(Image image)
Peilaa kuvan Y-suunnassa.
Definition: Image.cs:844