source: 2013/30/MiskaK/MW2(My Warfare 2)/Paranneltu Jypeli/Graphics/Animation.cs @ 4507

Revision 4507, 11.8 KB checked in by anlakane, 6 years ago (diff)

Talletus.

Line 
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
30using System;
31using System.Collections.Generic;
32
33
34namespace Jypeli
35{
36    /// <summary>
37    /// Sarja kuvia, jotka vaihtuvat halutulla nopeudella.
38    /// Yksi animaatio koostuu yhdestä tai useammasta kuvasta.
39    /// </summary>
40    /// <remarks>
41    /// Eri peliolioille kannattaa yleensä tehdä oma animaatio-olio,
42    /// jotta niiden animaatiot voivat edetä eri tahtiin. Jos animaatioilla
43    /// on kuitenkin samat kuvat, kannattaa samaa kuvataulukkoa käyttää
44    /// molemmille.
45    /// <example>
46    /// Image[] kuvat = LoadImages("kuva1", "kuva2", "kuva3");
47    ///
48    /// void LuoKentta()
49    /// {
50    ///     // ...
51    ///     o1.Animation = new animation(kuvat);
52    ///     o2.Animation = new Animation(kuvat);
53    /// }
54    /// </example>
55    /// </remarks>
56    public class Animation : IEnumerable<Image>
57    {
58        private double secondsPerFrame;
59        private TimeSpan startTime;
60        private bool isAnimated = false;
61        private int currentIndex;
62        private int repeatCount = -1; // When -1, animation repeats forever.
63
64        // NOTES:
65        //
66        // Animation frames should be immutable, because that is what
67        // the Layer class assumes. So, let's not provide
68        // any methods to modify the images of an existing animation.
69        //
70        // This is not a big deal, as there rarely is any need
71        // to modify animations at runtime and constructing new
72        // animation objects is quite easy anyway.
73
74#if !XBOX && !WINDOWS_PHONE
75        [NonSerialized]
76#endif
77        internal Image[] frames = null;
78
79        /// <summary>
80        /// Ruutujen määrä.
81        /// </summary>
82        public int FrameCount
83        {
84            get { return frames.Length; }
85        }
86
87        int lastRepeat = 0;
88
89        /// <summary>
90        /// Aktiivisen animaatioruudun indeksi (alkaa nollasta).
91        /// </summary>
92        public int CurrentFrameIndex
93        {
94            get
95            {
96                if ( !isAnimated ) return currentIndex;
97
98                double secondsNow = Game.Time.SinceStartOfGame.TotalSeconds;
99                double secondsAdvanced = secondsNow - startTime.TotalSeconds;
100                int currentRepeat = (int)( secondsAdvanced / ( FrameCount * secondsPerFrame ) );
101
102                if ( currentRepeat > lastRepeat )
103                {
104                    OnPlayed();
105                    lastRepeat = currentRepeat;
106                }
107                   
108                if ( repeatCount >= 0 && currentRepeat >= repeatCount )
109                    Stop();
110
111                return ( (int)( secondsAdvanced * FPS ) ) % FrameCount;
112            }
113        }
114
115        /// <summary>
116        /// Animaation päivitysnopeus ruutuina sekunnissa (frames per second).
117        /// </summary>
118        public double FPS
119        {
120            get { return 1 / secondsPerFrame; }
121            set
122            {
123                if ( value == 0 )
124                    throw new ArgumentException( "FPS can not be zero" );
125                secondsPerFrame = 1 / value;
126            }
127        }
128
129        /// <summary>
130        /// Tällä hetkellä näkyvä ruutu animaatiosta.
131        /// </summary>
132        public Image CurrentFrame
133        {
134            get { return frames[CurrentFrameIndex]; }
135        }
136
137        /// <summary>
138        /// Jos <c>true</c>, animaatio ei pysähtyessä palaa ensimmäiseen
139        /// ruutuun.
140        /// </summary>
141        public bool StopOnLastFrame { get; set; }
142
143        /// <summary>
144        /// Animaation leveys. Nolla, jos animaatiossa ei ole yhtään ruutua.
145        /// </summary>
146        public double Width
147        {
148            get { return FrameCount > 0 ? frames[0].Width : 0; }
149        }
150
151        /// <summary>
152        /// Animaation korkeus. Nolla, jos animaatiossa ei ole yhtään ruutua.
153        /// </summary>
154        public double Height
155        {
156            get { return FrameCount > 0 ? frames[0].Height : 0; }
157        }
158
159        /// <summary>
160        /// Animaation koko. Vector.Zero, jos animaatiossa ei ole yhtään ruutua.
161        /// </summary>
162        public Vector Size
163        {
164            get { return new Vector( Width, Height ); }
165        }
166
167        /// <summary>
168        /// Tapahtuma, joka tapahtuu kun animaatio on suoritettu.
169        /// </summary>
170        public event Action Played;
171
172        private void OnPlayed()
173        {
174            if ( Played != null ) Played();
175        }
176
177        /// <summary>
178        /// Luo uuden animaation.
179        /// </summary>
180        /// <param name="frames">Animaation ruudut.</param>
181        public Animation( params Image[] frames )
182        {
183            if ( frames.Length == 0 )
184                throw new ArgumentException( "Animation must have at least one frame." );
185            FPS = 25;
186            currentIndex = 0;
187            startTime = Game.Time.SinceStartOfGame;
188            this.frames = frames;
189        }
190
191        /// <summary>
192        /// Luo uuden animaation kuvasta.
193        /// </summary>
194        /// <param name="image">Kuva.</param>
195        public static implicit operator Animation(Image image)
196        {
197            if ( image == null ) return null;
198            return new Animation( image );
199        }
200
201        /// <summary>
202        /// Luo kopion jo tunnetusta animaatiosta.
203        /// </summary>
204        /// <param name="src">Kopioitava animaatio.</param>
205        public Animation( Animation src )
206        {
207            FPS = src.FPS;
208            isAnimated = src.isAnimated;
209            startTime = src.startTime;
210            currentIndex = src.currentIndex;
211            repeatCount = src.repeatCount;
212            frames = new Image[src.FrameCount];
213
214            // Copy only the references to images.
215            for ( int i = 0; i < src.FrameCount; i++ )
216                frames[i] = src.frames[i];
217        }
218
219        /// <summary>
220        /// Käyttää haluttua metodia kaikkiin animaation ruutuihin.
221        /// </summary>
222        /// <param name="anim">Animaatio</param>
223        /// <param name="method">Metodi, joka ottaa parametriksi kuvan ja palauttaa kuvan</param>
224        /// <returns>Uusi animaatio</returns>
225        public static Animation Apply( Animation anim, Converter<Image, Image> method )
226        {
227            Animation applied = new Animation( anim );
228
229            for ( int i = 0; i < anim.frames.Length; i++ )
230            {
231                applied.frames[i] = method(anim.frames[i]);
232            }
233
234            return applied;
235        }
236
237        /// <summary>
238        /// Peilaa animaation X-suunnasssa.
239        /// </summary>
240        /// <param name="anim">Animaatio</param>
241        /// <returns>Peilattu animaatio</returns>
242        public static Animation Mirror( Animation anim )
243        {
244            return Apply( anim, Image.Mirror );
245        }
246
247        /// <summary>
248        /// Peilaa animaation Y-suunnasssa.
249        /// </summary>
250        /// <param name="anim">Animaatio</param>
251        /// <returns>Peilattu animaatio</returns>
252        public static Animation Flip( Animation anim )
253        {
254            return Apply( anim, Image.Flip );
255        }
256
257        /// <summary>
258        /// Palauttaa animaation, joka toistuu lopusta alkuun.
259        /// </summary>
260        /// <param name="anim">Animaatio</param>
261        /// <returns>Käännetty animaatio</returns>
262        public static Animation Reverse( Animation anim )
263        {
264            Animation reversed = new Animation( anim );
265
266            for ( int i = 0; i < anim.frames.Length / 2; i++ )
267            {
268                reversed.frames[i] = anim.frames[anim.frames.Length - 1 - i];
269                reversed.frames[anim.frames.Length - 1 - i] = anim.frames[i];
270            }
271
272            return reversed;
273        }
274
275        /// <summary>
276        /// Käynnistää animaation alusta.
277        /// </summary>
278        public void Start()
279        {
280            Start( -1 );
281        }
282
283        /// <summary>
284        /// Käynnistää animaation alusta.
285        /// </summary>
286        /// <param name="repeatCount">Kuinka monta kertaa animaatio suoritetaan.</param>
287        public void Start( int repeatCount )
288        {
289            this.repeatCount = repeatCount;
290            startTime = Game.Time.SinceStartOfGame;
291            isAnimated = true;
292            lastRepeat = 0;
293        }
294
295        /// <summary>
296        /// Jatkaa animaatiota siitä, mihin viimeksi jäätiin.
297        /// </summary>
298        public void Resume()
299        {
300            isAnimated = true;
301        }
302
303        /// <summary>
304        /// Pysäyttää animaation asettaen sen ensimmäiseen ruutuun.
305        /// </summary>
306        public void Stop()
307        {
308            isAnimated = false;
309            currentIndex = 0;
310            if ( StopOnLastFrame )
311                currentIndex = FrameCount - 1;
312            repeatCount = -1;
313        }
314
315        /// <summary>
316        /// Etenee animaatiossa halutun määrän ruutuja. Käytä negatiivisia arvoja, jos haluat
317        /// kulkea taaksepäin.
318        /// </summary>
319        /// <param name="numberOfFrames">Edettävä määrä ruutuja.</param>
320        public void Step( int numberOfFrames )
321        {
322            if ( isAnimated )
323                Stop();
324           
325            //currentIndex = ( currentIndex + numberOfFrames ) % FrameCount;
326            currentIndex = currentIndex + numberOfFrames;
327
328            if ( currentIndex >= FrameCount )
329            {
330                // Animation has reached its final frame
331                if ( repeatCount > 0 ) repeatCount--;
332
333                if ( repeatCount == 0 )
334                    Stop();
335                else
336                {
337                    // Play it again, Sam
338                    currentIndex %= FrameCount;
339                }
340
341                OnPlayed();
342            }
343        }
344
345        /// <summary>
346        /// Etenee animaatiossa yhden ruudun eteenpäin.
347        /// </summary>
348        public void Step()
349        {
350            Step( 1 );
351        }
352
353        #region IEnumerable<Image> Members
354
355        public IEnumerator<Image> GetEnumerator()
356        {
357            foreach ( Image frame in frames )
358                yield return frame;
359        }
360
361        #endregion
362
363        #region IEnumerable Members
364
365        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
366        {
367            return frames.GetEnumerator();
368        }
369
370        #endregion
371    }
372}
Note: See TracBrowser for help on using the repository browser.