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

Revision 6548, 7.5 KB checked in by sieerinn, 4 years ago (diff)

Miekan (tai toistaiseksi pistoolin) heiluttelu.

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