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

Revision 6545, 7.9 KB checked in by sieerinn, 4 years ago (diff)

Animaatioiden latausjuttu ja pari animaatiota.

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 Creature(double width, double height)
42        : base(width, height)
43    {
44        LinearDamping = 0.5;
45    }
46
47    public void Move(Direction direction)
48    {
49        if (!Game.IsPaused)
50            Push(direction.GetVector() * MovementSpeed);
51    }
52}
53
54public partial class TheLegendOfGabriel : PhysicsGame
55{
56    public const int TILE_SIZE = 20;
57
58    private Creature player;
59
60    private bool transition;
61    List<GameObject> oldObjects = new List<GameObject>();
62    List<Exit> exits = new List<Exit>();
63
64    #region Resources
65
66    [AssetName("walkright")]
67    private Animation playerWalkRight;
68    [AssetName("walkright", mirror: true)]
69    private Animation playerWalkLeft;
70
71    #endregion
72
73    public override void Begin()
74    {
75        SmoothTextures = false;
76        LoadAnimations();
77        StartGame();
78    }
79
80    /// <summary>
81    /// Lataa automaagisesti kaikki animaatiot.
82    /// </summary>
83    private void LoadAnimations()
84    {
85        // Haetaan tämän luokan kaikki ei-julkiset attribuutit.
86        foreach (var field in GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
87        {
88            // Jos attribuutille on laitettu AsseName, niin ladataan sen niminen animaatio.
89            var assetAttr = Attribute.GetCustomAttribute(field, typeof(AssetNameAttribute)) as AssetNameAttribute;
90            if (assetAttr == null) continue;
91            var anim = LoadAnimation(assetAttr.AssetName);
92            field.SetValue(this, assetAttr.Mirror ? MirrorAnimation(anim) : anim);
93        }
94    }
95
96    /// <summary>
97    /// Peilaa kaikki animaation kuvat.
98    /// </summary>
99    private static Animation MirrorAnimation(Animation anim)
100    {
101        return new Animation(anim.Select(Image.Mirror).ToArray()) { FPS = anim.FPS };
102    }
103
104    private void StartGame()
105    {
106        ClearAll();
107        CreateLevel("level1");
108        //  CreatePlayer(new Vector(-Level.Width/3, Level.Bottom + TILE_SIZE * 2));
109        SetControls();
110        Camera.ZoomToLevel();
111    }
112
113    void SetControls()
114    {
115        Keyboard.Listen(Key.Left, ButtonState.Down, player.Move, null, Direction.Left);
116        Keyboard.Listen(Key.Right, ButtonState.Down, player.Move, null, Direction.Right);
117        Keyboard.Listen(Key.Up, ButtonState.Down, player.Move, null, Direction.Up);
118        Keyboard.Listen(Key.Down, ButtonState.Down, player.Move, null, Direction.Down);
119
120        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, null);
121    }
122
123    ///// <summary>
124    ///// Luo pelaajan.
125    ///// </summary>
126    //void CreatePlayer(Vector position)
127    //{
128    //    player = new Creature(TILE_SIZE, TILE_SIZE);
129    //    player.MovementSpeed = 2300;
130    //    player.Position = position;
131    //    Add(player);
132
133    //    AddCollisionHandler(player, "exit", CollidesWithExit);
134    //}
135
136    void CollidesWithExit(PhysicsObject pPlayer, PhysicsObject pExit)
137    {
138        var oldExit = pExit as Exit;
139        if (oldExit == null || transition)
140            return;
141
142        transition = true;
143
144        // Otetaan vanhat objektit talteen.
145        oldObjects.Clear();
146        foreach (var obj in GetObjects(o => o != player))
147        {
148            if (obj != player)
149            {
150                oldObjects.Add(obj);
151            }
152        }
153
154        // Luodaan seuraava kenttä.
155        exits.Clear();
156        CreateLevel(oldExit.TargetLevel);
157
158        // Etsitään seuraavan kentän kohde exitti johon siirrytään.
159        var targetExit = exits.FirstOrDefault(e => e.Name == oldExit.TargetExitName);
160
161        // Jompikumpi uloskäynti ei ole kentän laidalla, sulava siirtyminen ei ole mahdollista.
162        if (GetExitDirection(targetExit) == Direction.None || GetExitDirection(oldExit) == Direction.None)
163        {
164            transition = false;
165            oldObjects.ForEach(o => o.Destroy());
166            oldObjects.Clear();
167
168            // Yritetään päätellä pelaajalle joku järkevä paikka.
169            player.Position = targetExit.Position + Direction.Inverse(targetExit.Position.Angle.MainDirection).GetVector() * TILE_SIZE * 2;
170            Camera.ZoomToLevel();
171            return;
172        }
173
174        // Pysäytetään peli siirtymän ajaksi.
175        Pause();
176        PhysicsEnabled = false;
177
178        // Lasketaan siirtymävektorit.
179        Direction dir = GetExitDirection(targetExit);
180        Vector exitDelta = targetExit.Position - oldExit.Position;
181        Vector transitionVector = Level.Size;
182        if (dir == Direction.Left || dir == Direction.Right)
183        {
184            transitionVector.X *= dir.GetVector().X;
185            transitionVector.Y = exitDelta.Y;
186        }
187        else
188        {
189            transitionVector.Y *= dir.GetVector().Y;
190            transitionVector.X = exitDelta.X;
191        }
192
193        // Siirretään vanhoja objekteja ja pelaajaa.
194        foreach (var obj in oldObjects)
195        {
196            obj.Position += transitionVector;
197        }
198        player.Position += transitionVector + Direction.Inverse(dir).GetVector() * TILE_SIZE * 4;
199
200        // Zoomataan kameraa sopivasti ja liikutetaan se vanhan kentän päälle, josta se sitten siirtyy uuden kentän päälle.
201        Camera.Position += transitionVector;
202        Vector pos = Camera.Position;
203        Camera.ZoomToLevel();
204        Camera.Position = pos;
205    }
206
207    /// <summary>
208    /// Palauttaa suunnan millä puolella kenttää uloskäynti on.
209    /// </summary>   
210    Direction GetExitDirection(Exit exit)
211    {
212        const double epsilon = 1e-3;
213        Func<double, double, bool> isSame = (x, y) => Math.Abs(y - x) < epsilon;
214
215        if (isSame(exit.Top, Level.Top))
216        {
217            return Direction.Up;
218        }
219        if (isSame(exit.Bottom, Level.Bottom))
220        {
221            return Direction.Down;
222        }
223        if (isSame(exit.Left, Level.Left))
224        {
225            return Direction.Left;
226        }
227        if (isSame(exit.Right, Level.Right))
228        {
229            return Direction.Right;
230        }
231        return Direction.None;
232    }
233
234    protected override void PausedUpdate(Time gameTime)
235    {
236        base.PausedUpdate(gameTime);
237        double dt = gameTime.SinceLastUpdate.TotalSeconds;
238
239        const double transitionSpeed = 500.0;
240
241        if (transition)
242        {
243            Camera.Position += Camera.Position.Normalize() * -transitionSpeed * dt;
244
245            // Siirtymä on ohi, jatketaan peliä ja poistetaan edellinen kenttä.
246            if (Camera.Position.Magnitude < transitionSpeed * dt)
247            {
248                transition = false;
249                Pause();
250                PhysicsEnabled = true;
251                Camera.Position = Vector.Zero;
252
253                foreach (var obj in oldObjects)
254                {
255                    obj.Destroy();
256                }
257                oldObjects.Clear();
258            }
259        }
260    }
261}
Note: See TracBrowser for help on using the repository browser.