source: 2015/27/ohjaajat/TheLegendOfGabriel/TheLegendOfGabriel/TheLegendOfGabriel/TheLegendOfGabriel.cs @ 6546

Revision 6546, 9.1 KB checked in by sieerinn, 4 years ago (diff)

Pelaajalla on animaatiot.

Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Reflection;
5using Jypeli;
6using Jypeli.Assets;
7using Jypeli.Controls;
8using Jypeli.Effects;
9using Jypeli.Widgets;
10
11sealed class Exit : PhysicsObject
12{
13    /// <summary>
14    /// Kentän nimi johon siirrytään.
15    /// </summary>
16    public string TargetLevel { get; set; }
17
18    /// <summary>
19    /// Kohdekentässä olevan exitin nimi jonka päältä aloitetaan.
20    /// </summary>
21    public string TargetExitName { get; set; }
22
23    /// <summary>
24    /// Tämän uloskäynnin nimi.
25    /// </summary>
26    public string Name { get; set; }
27
28    public Exit(double width, double height)
29        : base(width, height)
30    {
31        Color = new Color(255, 0, 0, 60); // Debuggausta varten jotta näkee uloskäynnit.
32        IgnoresCollisionResponse = true;
33        Tag = "exit";
34    }
35}
36
37class Creature : PhysicsObject
38{
39    public double MovementSpeed { get; set; }
40
41    public Dictionary<Direction, Animation> MoveAnimations { get; set; }
42
43    public Creature(double width, double height)
44        : base(width, height)
45    {
46        MoveAnimations = new Dictionary<Direction, Animation>();
47        LinearDamping = 0.5;
48    }
49
50    public void Move(Direction direction)
51    {
52        if (!Game.IsPaused)
53            Push(direction.GetVector() * MovementSpeed);
54    }
55
56    public override void Update(Time time)
57    {
58        if (Velocity.MagnitudeSquared > 10.0)
59        {
60            // Animaation vaihto nopeuden suunnan perusteella.
61            Animation newAnim;
62            var dir = Velocity.Angle.MainDirection;
63            if (MoveAnimations.TryGetValue(dir, out newAnim))
64            {
65                if (Animation != newAnim)
66                {
67                    Animation = newAnim;
68                }
69            }
70
71            // Käynnistetään animaatio jos se ei ole jo käynnissä.
72            if (!Animation.IsPlaying)
73                Animation.Resume();
74        }
75        else if (Animation != null && Animation.IsPlaying)
76        {
77            // Paikallaan ollessa pysäytetään animaatio.
78            Animation.Pause();
79        }
80        base.Update(time);
81    }
82}
83
84public partial class TheLegendOfGabriel : PhysicsGame
85{
86    public const int TILE_SIZE = 20;
87
88    private Creature player;
89
90    private bool transition;
91    List<GameObject> oldObjects = new List<GameObject>();
92    List<Exit> exits = new List<Exit>();
93
94    #region Resources
95
96    [AssetName("walkright")]
97    private Animation playerWalkRight;
98    [AssetName("walkright", mirror: true)]
99    private Animation playerWalkLeft;
100    [AssetName("walkup")]
101    private Animation playerWalkUp;
102    [AssetName("walkdown")]
103    private Animation playerWalkDown;
104
105    #endregion
106
107    public override void Begin()
108    {
109        SmoothTextures = false;
110        LoadAnimations();
111        StartGame();
112    }
113
114    /// <summary>
115    /// Lataa automaagisesti kaikki animaatiot.
116    /// </summary>
117    private void LoadAnimations()
118    {
119        // Haetaan tämän luokan kaikki ei-julkiset attribuutit.
120        foreach (var field in GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
121        {
122            // Jos attribuutille on laitettu AsseName, niin ladataan sen niminen animaatio.
123            var assetAttr = Attribute.GetCustomAttribute(field, typeof(AssetNameAttribute)) as AssetNameAttribute;
124            if (assetAttr == null) continue;
125            var anim = LoadAnimation(assetAttr.AssetName);
126            field.SetValue(this, assetAttr.Mirror ? MirrorAnimation(anim) : anim);
127        }
128    }
129
130    /// <summary>
131    /// Peilaa kaikki animaation kuvat.
132    /// </summary>
133    private static Animation MirrorAnimation(Animation anim)
134    {
135        return new Animation(anim.Select(Image.Mirror).ToArray()) { FPS = anim.FPS };
136    }
137
138    private void StartGame()
139    {
140        ClearAll();
141        CreateLevel("level1");
142        //  CreatePlayer(new Vector(-Level.Width/3, Level.Bottom + TILE_SIZE * 2));
143        SetControls();
144        Camera.ZoomToLevel();
145    }
146
147    void SetControls()
148    {
149        Keyboard.Listen(Key.Left, ButtonState.Down, player.Move, null, Direction.Left);
150        Keyboard.Listen(Key.Right, ButtonState.Down, player.Move, null, Direction.Right);
151        Keyboard.Listen(Key.Up, ButtonState.Down, player.Move, null, Direction.Up);
152        Keyboard.Listen(Key.Down, ButtonState.Down, player.Move, null, Direction.Down);
153
154        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, null);
155    }
156
157    ///// <summary>
158    ///// Luo pelaajan.
159    ///// </summary>
160    //void CreatePlayer(Vector position)
161    //{
162    //    player = new Creature(TILE_SIZE, TILE_SIZE);
163    //    player.MovementSpeed = 2300;
164    //    player.Position = position;
165    //    Add(player);
166
167    //    AddCollisionHandler(player, "exit", CollidesWithExit);
168    //}
169
170    void CollidesWithExit(PhysicsObject pPlayer, PhysicsObject pExit)
171    {
172        var oldExit = pExit as Exit;
173        if (oldExit == null || transition)
174            return;
175
176        transition = true;
177
178        // Otetaan vanhat objektit talteen.
179        oldObjects.Clear();
180        foreach (var obj in GetObjects(o => o != player))
181        {
182            if (obj != player)
183            {
184                oldObjects.Add(obj);
185            }
186        }
187
188        // Luodaan seuraava kenttä.
189        exits.Clear();
190        CreateLevel(oldExit.TargetLevel);
191
192        // Etsitään seuraavan kentän kohde exitti johon siirrytään.
193        var targetExit = exits.FirstOrDefault(e => e.Name == oldExit.TargetExitName);
194
195        // Jompikumpi uloskäynti ei ole kentän laidalla, sulava siirtyminen ei ole mahdollista.
196        if (GetExitDirection(targetExit) == Direction.None || GetExitDirection(oldExit) == Direction.None)
197        {
198            transition = false;
199            oldObjects.ForEach(o => o.Destroy());
200            oldObjects.Clear();
201
202            // Yritetään päätellä pelaajalle joku järkevä paikka.
203            player.Position = targetExit.Position + Direction.Inverse(targetExit.Position.Angle.MainDirection).GetVector() * TILE_SIZE * 2;
204            Camera.ZoomToLevel();
205            return;
206        }
207
208        // Pysäytetään peli siirtymän ajaksi.
209        Pause();
210        PhysicsEnabled = false;
211
212        // Lasketaan siirtymävektorit.
213        Direction dir = GetExitDirection(targetExit);
214        Vector exitDelta = targetExit.Position - oldExit.Position;
215        Vector transitionVector = Level.Size;
216        if (dir == Direction.Left || dir == Direction.Right)
217        {
218            transitionVector.X *= dir.GetVector().X;
219            transitionVector.Y = exitDelta.Y;
220        }
221        else
222        {
223            transitionVector.Y *= dir.GetVector().Y;
224            transitionVector.X = exitDelta.X;
225        }
226
227        // Siirretään vanhoja objekteja ja pelaajaa.
228        foreach (var obj in oldObjects)
229        {
230            obj.Position += transitionVector;
231        }
232        player.Position += transitionVector + Direction.Inverse(dir).GetVector() * TILE_SIZE * 4;
233
234        // Zoomataan kameraa sopivasti ja liikutetaan se vanhan kentän päälle, josta se sitten siirtyy uuden kentän päälle.
235        Camera.Position += transitionVector;
236        Vector pos = Camera.Position;
237        Camera.ZoomToLevel();
238        Camera.Position = pos;
239    }
240
241    /// <summary>
242    /// Palauttaa suunnan millä puolella kenttää uloskäynti on.
243    /// </summary>   
244    Direction GetExitDirection(Exit exit)
245    {
246        const double epsilon = 1e-3;
247        Func<double, double, bool> isSame = (x, y) => Math.Abs(y - x) < epsilon;
248
249        if (isSame(exit.Top, Level.Top))
250        {
251            return Direction.Up;
252        }
253        if (isSame(exit.Bottom, Level.Bottom))
254        {
255            return Direction.Down;
256        }
257        if (isSame(exit.Left, Level.Left))
258        {
259            return Direction.Left;
260        }
261        if (isSame(exit.Right, Level.Right))
262        {
263            return Direction.Right;
264        }
265        return Direction.None;
266    }
267
268    protected override void PausedUpdate(Time gameTime)
269    {
270        base.PausedUpdate(gameTime);
271        double dt = gameTime.SinceLastUpdate.TotalSeconds;
272
273        const double transitionSpeed = 500.0;
274
275        if (transition)
276        {
277            Camera.Position += Camera.Position.Normalize() * -transitionSpeed * dt;
278
279            // Siirtymä on ohi, jatketaan peliä ja poistetaan edellinen kenttä.
280            if (Camera.Position.Magnitude < transitionSpeed * dt)
281            {
282                transition = false;
283                Pause();
284                PhysicsEnabled = true;
285                Camera.Position = Vector.Zero;
286
287                foreach (var obj in oldObjects)
288                {
289                    obj.Destroy();
290                }
291                oldObjects.Clear();
292            }
293        }
294    }
295
296    protected override void Update(Time time)
297    {
298        player.Update(time);
299        base.Update(time);
300    }
301}
Note: See TracBrowser for help on using the repository browser.