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

Revision 6618, 12.7 KB checked in by empaheik, 4 years ago (diff)
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
11public class StoryItem
12{
13    // Iso kuvake joka näkyy inventoryssä.
14    public Image InventoryImage { get; set; }
15
16    public Queue<string> Message { get; set; }
17
18    public StoryItem(Queue<String> message, Image image)
19    {
20        this.InventoryImage = image;
21        this.Message = message;
22    }
23}
24
25public partial class TheLegendOfGabriel : PhysicsGame
26{
27    public const int TILE_SIZE = 20;
28
29    private Player player;
30
31    private bool transition;
32    List<GameObject> oldObjects = new List<GameObject>();
33    List<Exit> exits = new List<Exit>();
34
35    private bool viewing;
36    private double midpoint;
37    private double second;
38    GameObject frame;
39    Queue<string> messagesviewed;
40
41    private const int STORYITEM_COUNT = 3;
42    StoryItem[] storyItem = new StoryItem[3];
43
44    #region Resources
45
46    public static Image GunImage = LoadImage("gun");
47    public static Image LetterImage = LoadImage("letter");
48    public static Image SmallSwordImage = LoadImage("smallsword");
49
50    public static Image FrameImage = LoadImage("frame");
51
52    [AssetName("walkright")]
53    internal Animation playerWalkRight;
54    [AssetName("walkright", mirror: true)]
55    internal Animation playerWalkLeft;
56    [AssetName("walkup")]
57    private Animation playerWalkUp;
58    [AssetName("walkdown")]
59    private Animation playerWalkDown;
60
61    [AssetName("swingup")]
62    private Animation playerSwingUp;
63    [AssetName("swingright")]
64    private Animation playerSwingRight;
65    [AssetName("swingright", mirror: true)]
66    private Animation playerSwingLeft;
67    [AssetName("swingdown")]
68    private Animation playerSwingDown;
69
70    [AssetName("shootup")]
71    private Animation playerShootUp;
72    [AssetName("shootright")]
73    private Animation playerShootRight;
74    [AssetName("shootright", mirror: true)]
75    private Animation playerShootLeft;
76    [AssetName("shootdown")]
77    private Animation playerShootDown;
78
79    #endregion
80
81    public override void Begin()
82    {
83        Mouse.IsCursorVisible = true;
84        SmoothTextures = false;
85        LoadAnimations();
86        StartGame();
87        Intro();
88        BuildRightBar();
89    }
90
91    void BuildRightBar()
92    {
93        for (int i = 0; i < STORYITEM_COUNT; i++)
94        {
95            GameObject member = new GameObject(FrameImage);
96            member.Position = new Vector(Level.Right + FrameImage.Width, Level.Top - Level.Width * 0.25 - FrameImage.Height * i * 1.5);
97            Add(member);
98
99            GameObject inner = new GameObject(TILE_SIZE, TILE_SIZE);
100            inner.Color = Color.Black;
101            if (storyItem[i] != null)
102            {
103                inner.Image = storyItem[i].InventoryImage;
104                Mouse.ListenOn(inner, MouseButton.Left, ButtonState.Pressed, ShowTextItem, "View those precious memories", storyItem[i]);
105            }
106            member.Add(inner);
107        }
108    }
109
110    /// <summary>
111    /// Lataa automaagisesti kaikki animaatiot.
112    /// </summary>
113    private void LoadAnimations()
114    {
115        // Haetaan tämän luokan kaikki ei-julkiset attribuutit.
116        foreach (var field in GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
117        {
118            // Jos attribuutille on laitettu AsseName, niin ladataan sen niminen animaatio.
119            var assetAttr = Attribute.GetCustomAttribute(field, typeof(AssetNameAttribute)) as AssetNameAttribute;
120            if (assetAttr == null) continue;
121            var anim = LoadAnimation(assetAttr.AssetName);
122            field.SetValue(this, assetAttr.Mirror ? MirrorAnimation(anim) : anim);
123        }
124    }
125
126    void Intro()
127    {
128        storyItem[0] = new StoryItem(new Queue<string>(new[] { "Dear Alexander,", 
129            "",
130            "",
131            "I have accepted a position at the Communal Assets for Justice.",
132            "Please do not consider this an act of rejection. I am simply",
133            "a victim to the scathing uncertainty of your release from service.",
134            "",
135            "I still see your face in my dreams. I believe that when",
136            "our immediate circumstances change, we'll meet again, we'll",
137            "work it out. Were you here, we'd certainly fall in love.",
138            "",
139            "And perhaps then nothing could keep us apart.",
140            "-Ana" 
141        }), LetterImage);
142
143        ShowTextItem(storyItem[0]);
144    }
145
146    void ShowTextItem(StoryItem item)
147    {
148        viewing = true;
149        messagesviewed = new Queue<string>(item.Message);
150        Pause();
151
152        Level.AmbientLight -= 0.75;
153
154        frame = new GameObject(LetterImage);
155        frame.Image = LetterImage;
156        frame.Width = Window.Width * 0.25;
157        frame.Height = Window.Height * 0.25;
158        Add(frame);
159
160        midpoint = 26 * item.Message.Count() * 0.5;
161
162    }
163
164    /// <summary>
165    /// Peilaa kaikki animaation kuvat.
166    /// </summary>
167    private static Animation MirrorAnimation(Animation anim)
168    {
169        return new Animation(anim.Select(Image.Mirror).ToArray()) { FPS = anim.FPS };
170    }
171
172    private void StartGame()
173    {
174        ClearAll();
175        CreateLevel("level1");
176        //CreatePlayer(new Vector(-Level.Width/3, Level.Bottom + TILE_SIZE * 2));
177        SetControls();
178        Camera.ZoomToLevel();
179    }
180
181    void SetControls()
182    {
183        Keyboard.Listen(Key.Left, ButtonState.Down, player.Move, null, Direction.Left);
184        Keyboard.Listen(Key.Right, ButtonState.Down, player.Move, null, Direction.Right);
185        Keyboard.Listen(Key.Up, ButtonState.Down, player.Move, null, Direction.Up);
186        Keyboard.Listen(Key.Down, ButtonState.Down, player.Move, null, Direction.Down);
187
188        Keyboard.Listen(Key.Space, ButtonState.Pressed, delegate { if (player.ActiveItem != null) player.ActiveItem.UseKeyPressed(); }, null);
189        Keyboard.Listen(Key.Space, ButtonState.Released, delegate { if (player.ActiveItem != null) player.ActiveItem.UseKeyReleased(); }, null);
190        Keyboard.Listen(Key.Space, ButtonState.Down, delegate { if (player.ActiveItem != null) player.ActiveItem.UseKeyDown(); }, null);
191
192        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, null);
193    }
194
195    ///// <summary>
196    ///// Luo pelaajan.
197    ///// </summary>
198    //void CreatePlayer(Vector position)
199    //{
200    //    player = new Creature(TILE_SIZE, TILE_SIZE);
201    //    player.MovementSpeed = 2300;
202    //    player.Position = position;
203    //    Add(player);
204
205    //    AddCollisionHandler(player, "exit", CollidesWithExit);
206    //}
207
208    void CollidesWithExit(PhysicsObject pPlayer, PhysicsObject pExit)
209    {
210        var oldExit = pExit as Exit;
211        if (oldExit == null || transition)
212            return;
213
214        transition = true;
215
216        // Otetaan vanhat objektit talteen.
217        oldObjects.Clear();
218        foreach (var obj in GetObjects(o => o != player))
219        {
220            if (obj != player)
221            {
222                oldObjects.Add(obj);
223            }
224        }
225
226        // Luodaan seuraava kenttä.
227        exits.Clear();
228        CreateLevel(oldExit.TargetLevel);
229
230        // Etsitään seuraavan kentän kohde exitti johon siirrytään.
231        var targetExit = exits.FirstOrDefault(e => e.Name == oldExit.TargetExitName);
232
233        // Jompikumpi uloskäynti ei ole kentän laidalla, sulava siirtyminen ei ole mahdollista.
234        if (GetExitDirection(targetExit) == Direction.None || GetExitDirection(oldExit) == Direction.None)
235        {
236            transition = false;
237            oldObjects.ForEach(o => o.Destroy());
238            oldObjects.Clear();
239
240            // Yritetään päätellä pelaajalle joku järkevä paikka.
241            player.Position = targetExit.Position + Direction.Inverse(targetExit.Position.Angle.MainDirection).GetVector() * TILE_SIZE * 2;
242            Camera.ZoomToLevel();
243            return;
244        }
245
246        // Pysäytetään peli siirtymän ajaksi.
247        Pause();
248        PhysicsEnabled = false;
249
250        // Lasketaan siirtymävektorit.
251        Direction dir = GetExitDirection(targetExit);
252        Vector exitDelta = targetExit.Position - oldExit.Position;
253        Vector transitionVector = Level.Size;
254        if (dir == Direction.Left || dir == Direction.Right)
255        {
256            transitionVector.X *= dir.GetVector().X;
257            transitionVector.Y = exitDelta.Y;
258        }
259        else
260        {
261            transitionVector.Y *= dir.GetVector().Y;
262            transitionVector.X = exitDelta.X;
263        }
264
265        // Siirretään vanhoja objekteja ja pelaajaa.
266        foreach (var obj in oldObjects)
267        {
268            obj.Position += transitionVector;
269        }
270        player.Position += transitionVector + Direction.Inverse(dir).GetVector() * TILE_SIZE * 4;
271
272        // Zoomataan kameraa sopivasti ja liikutetaan se vanhan kentän päälle, josta se sitten siirtyy uuden kentän päälle.
273        Camera.Position += transitionVector;
274        Vector pos = Camera.Position;
275        Camera.ZoomToLevel();
276        Camera.Position = pos;
277    }
278
279    /// <summary>
280    /// Palauttaa suunnan millä puolella kenttää uloskäynti on.
281    /// </summary>   
282    Direction GetExitDirection(Exit exit)
283    {
284        const double epsilon = 1e-3;
285        Func<double, double, bool> isSame = (x, y) => Math.Abs(y - x) < epsilon;
286
287        if (isSame(exit.Top, Level.Top))
288        {
289            return Direction.Up;
290        }
291        if (isSame(exit.Bottom, Level.Bottom))
292        {
293            return Direction.Down;
294        }
295        if (isSame(exit.Left, Level.Left))
296        {
297            return Direction.Left;
298        }
299        if (isSame(exit.Right, Level.Right))
300        {
301            return Direction.Right;
302        }
303        return Direction.None;
304    }
305
306    protected override void PausedUpdate(Time gameTime)
307    {
308        base.PausedUpdate(gameTime);
309        double dt = gameTime.SinceLastUpdate.TotalSeconds;
310
311        const double transitionSpeed = 500.0;
312
313        if (transition && !viewing)
314        {
315            Camera.Position += Camera.Position.Normalize() * -transitionSpeed * dt;
316
317            // Siirtymä on ohi, jatketaan peliä ja poistetaan edellinen kenttä.
318            if (Camera.Position.Magnitude < transitionSpeed * dt)
319            {
320                transition = false;
321                Pause();
322                PhysicsEnabled = true;
323                Camera.Position = Vector.Zero;
324
325                foreach (var obj in oldObjects)
326                {
327                    obj.Destroy();
328                }
329                oldObjects.Clear();
330            }
331        }
332
333        if(viewing && !transition)  //!transition perhaps being somewhat unnecessary, but now I do feel a bit safer.
334        {
335            second += dt;
336            if(second > 1)
337            {
338                if (messagesviewed.Count < 1)   //The letter's read, we better head back.
339                {
340                    Level.AmbientLight = 1;
341                    frame.Destroy();
342                    GetObjectsWithTag("labelWaitingToDie").ForEach(g => g.Destroy());
343                    viewing = false;
344                    Pause();
345                    return;
346                }
347
348                second = 0;
349                var storyLabel = new Label(messagesviewed.Dequeue()) { TextColor = Color.White };
350                storyLabel.Y = -midpoint + storyLabel.Height * messagesviewed.Count() + 1;
351                storyLabel.Tag = "labelWaitingToDie";
352                Add(storyLabel);
353
354            }
355            //Timer textTimer = new Timer();
356            //textTimer.Interval = 1;
357            //textTimer.Timeout += delegate
358            //{
359            //    if (messages.Count < 1)
360            //    {
361            //        Keyboard.EnableAll();
362            //        Level.AmbientLight = 1;
363            //        frame.Destroy();
364            //        GetObjectsWithTag("labelWaitingToDie").ForEach(g => g.Destroy());
365            //        textTimer.Stop();
366            //        Pause();
367            //        return;
368            //    }
369
370            //    var storyLabel = new Label(messages.Dequeue()) { TextColor = Color.White };
371            //    storyLabel.Y = -midpoint + storyLabel.Height * messages.Count() + 1;
372            //    storyLabel.Tag = "labelWaitingToDie";
373            //    Add(storyLabel);
374            //};
375            //textTimer.Start();
376        }
377    }
378
379    protected override void Update(Time time)
380    {
381        player.UpdateCreature(time);
382        base.Update(time);
383    }
384}
Note: See TracBrowser for help on using the repository browser.