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

Revision 6623, 16.0 KB checked in by sieerinn, 4 years ago (diff)

Inventoryjuttua päivitetty.

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    private Label currentItem;
45    private Label nextItem;
46    private Label prevItem;
47    private Label swordFrame;
48
49    #region Resources
50
51    public static Image GunImage = LoadImage("gun");
52    public static Image LetterImage = LoadImage("letter");
53    public static Image SmallSwordImage = LoadImage("smallsword");
54    public static Image MonocleImage = LoadImage("monocle");
55    public static Image BigMonocleImage = LoadImage("bigmonocle");
56    public static Image BigSwordImage = LoadImage("bigsword");
57
58    public static Image FrameImage = LoadImage("frame");
59    public static Image ActiveItemFrameImageX = LoadImage("activeitemframe");
60    public static Image ActiveItemFrameImageZ = LoadImage("activeitemframez");
61
62    [AssetName("walkright")]
63    internal Animation playerWalkRight;
64    [AssetName("walkright", mirror: true)]
65    internal Animation playerWalkLeft;
66    [AssetName("walkup")]
67    private Animation playerWalkUp;
68    [AssetName("walkdown")]
69    private Animation playerWalkDown;
70
71    [AssetName("swingup")]
72    private Animation playerSwingUp;
73    [AssetName("swingright")]
74    private Animation playerSwingRight;
75    [AssetName("swingright", mirror: true)]
76    private Animation playerSwingLeft;
77    [AssetName("swingdown")]
78    private Animation playerSwingDown;
79
80    [AssetName("shootup")]
81    private Animation playerShootUp;
82    [AssetName("shootright")]
83    private Animation playerShootRight;
84    [AssetName("shootright", mirror: true)]
85    private Animation playerShootLeft;
86    [AssetName("shootdown")]
87    private Animation playerShootDown;
88
89    #endregion
90
91    public override void Begin()
92    {
93        Mouse.IsCursorVisible = true;
94        SmoothTextures = false;
95        LoadAnimations();
96        StartGame();
97        //Intro();
98        BuildRightBar();
99        BuildInventoryCycle();
100        UpdateItemCycleImages();
101    }
102
103    void BuildInventoryCycle()
104    {
105        const int spacing = 20;
106
107        prevItem = new Label();
108        prevItem.Size = new Vector(60, 40);
109        prevItem.X = Screen.Left + 100;
110        prevItem.Y = Screen.Top - 50;
111        Add(prevItem);
112
113        currentItem = new Label();
114        currentItem.Size = prevItem.Size;
115        currentItem.Left = prevItem.Right + spacing;
116        currentItem.Y = prevItem.Y;
117        Add(currentItem);
118
119        nextItem = new Label();
120        nextItem.Size = prevItem.Size;
121        nextItem.Left = currentItem.Right + spacing;
122        nextItem.Y = prevItem.Y;
123        Add(nextItem);
124
125        var frame = new Label();
126        frame.Size = new Vector(60, 60);
127        frame.Image = ActiveItemFrameImageX;
128        frame.X = currentItem.X;
129        frame.Top = currentItem.Top;
130        Add(frame);
131
132        swordFrame = new Label();
133        swordFrame.Size = prevItem.Size;
134        swordFrame.Left = nextItem.Right + spacing * 2;
135        swordFrame.Top = currentItem.Top;
136        Add(swordFrame);
137
138        var frame2 = new Label();
139        frame2.Size = new Vector(60, 60);
140        frame2.Image = ActiveItemFrameImageZ;
141        frame2.X = swordFrame.X;
142        frame2.Top = swordFrame.Top;
143        Add(frame2);
144    }
145
146    void BuildRightBar()
147    {
148        for (int i = 0; i < STORYITEM_COUNT; i++)
149        {
150            GameObject member = new GameObject(FrameImage);
151            member.Position = new Vector(Level.Right + FrameImage.Width, Level.Top - Level.Width * 0.25 - FrameImage.Height * i * 1.5);
152            Add(member);
153
154            GameObject inner = new GameObject(TILE_SIZE, TILE_SIZE);
155            inner.Color = Color.Black;
156            if (storyItem[i] != null)
157            {
158                inner.Image = storyItem[i].InventoryImage;
159                Mouse.ListenOn(inner, MouseButton.Left, ButtonState.Pressed, ShowTextItem, "View those precious memories", storyItem[i]);
160            }
161            member.Add(inner);
162        }
163    }
164    /// <summary>
165    /// Lataa automaagisesti kaikki animaatiot.
166    /// </summary>
167    private void LoadAnimations()
168    {
169        // Haetaan tämän luokan kaikki ei-julkiset attribuutit.
170        foreach (var field in GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
171        {
172            // Jos attribuutille on laitettu AsseName, niin ladataan sen niminen animaatio.
173            var assetAttr = Attribute.GetCustomAttribute(field, typeof(AssetNameAttribute)) as AssetNameAttribute;
174            if (assetAttr == null) continue;
175            var anim = LoadAnimation(assetAttr.AssetName);
176            field.SetValue(this, assetAttr.Mirror ? MirrorAnimation(anim) : anim);
177        }
178    }
179
180    void Intro()
181    {
182        storyItem[0] = new StoryItem(new Queue<string>(new[] { "Dear Alexander,", 
183            "",
184            "",
185            "I have accepted a position at the Communal Assets for Justice.",
186            "Please do not consider this an act of rejection. I am simply",
187            "a victim to the scathing uncertainty of your release from service.",
188            "",
189            "I still see your face in my dreams. I believe that when",
190            "our immediate circumstances change, we'll meet again, we'll",
191            "work it out. Were you here, we'd certainly fall in love.",
192            "",
193            "And perhaps then nothing could keep us apart.",
194            "-Ana" 
195        }), LetterImage);
196
197        ShowTextItem(storyItem[0]);
198    }
199
200    void ShowTextItem(StoryItem item)
201    {
202        viewing = true;
203        messagesviewed = new Queue<string>(item.Message);
204        Pause();
205
206        Level.AmbientLight -= 0.75;
207
208        frame = new GameObject(LetterImage);
209        frame.Image = LetterImage;
210        frame.Width = Window.Width * 0.25;
211        frame.Height = Window.Height * 0.25;
212        Add(frame);
213
214        midpoint = 26 * item.Message.Count() * 0.5;
215
216    }
217
218    /// <summary>
219    /// Peilaa kaikki animaation kuvat.
220    /// </summary>
221    private static Animation MirrorAnimation(Animation anim)
222    {
223        return new Animation(anim.Select(Image.Mirror).ToArray()) { FPS = anim.FPS };
224    }
225
226    private void StartGame()
227    {
228        ClearAll();
229        CreateLevel("level1");
230        //CreatePlayer(new Vector(-Level.Width/3, Level.Bottom + TILE_SIZE * 2));
231        SetControls();
232        Camera.ZoomToLevel();
233    }
234
235    void SetControls()
236    {
237        Keyboard.Listen(Key.Left, ButtonState.Down, player.Move, null, Direction.Left);
238        Keyboard.Listen(Key.Right, ButtonState.Down, player.Move, null, Direction.Right);
239        Keyboard.Listen(Key.Up, ButtonState.Down, player.Move, null, Direction.Up);
240        Keyboard.Listen(Key.Down, ButtonState.Down, player.Move, null, Direction.Down);
241
242        Keyboard.Listen(Key.X, ButtonState.Pressed, delegate { UseItem(player.ActiveItem, player.Sword, () => player.ActiveItem.UseKeyPressed()); }, null);
243        Keyboard.Listen(Key.X, ButtonState.Released, delegate { UseItem(player.ActiveItem, player.Sword, () => player.ActiveItem.UseKeyReleased()); }, null);
244        Keyboard.Listen(Key.X, ButtonState.Down, delegate { UseItem(player.ActiveItem, player.Sword, () => player.ActiveItem.UseKeyDown()); }, null);
245
246        Keyboard.Listen(Key.Z, ButtonState.Pressed, delegate { UseItem(player.Sword, player.ActiveItem, () => player.Sword.UseKeyPressed()); }, null);
247        Keyboard.Listen(Key.Z, ButtonState.Released, delegate { UseItem(player.Sword, player.ActiveItem, () => player.Sword.UseKeyReleased()); }, null);
248        Keyboard.Listen(Key.Z, ButtonState.Down, delegate { UseItem(player.Sword, player.ActiveItem, () => player.Sword.UseKeyDown()); }, null);
249
250        Keyboard.Listen(Key.Space, ButtonState.Pressed, CycleItems, null);
251
252        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, null);
253    }
254
255    void UseItem(Item item, Item otherItem, Action action)
256    {
257        bool inUse = false;
258        if (otherItem != null)
259        {
260            inUse = otherItem.InUse;
261        }
262
263        if (item != null && !inUse)
264        {
265            action();
266        }
267    }
268
269    void CycleItems()
270    {
271        // Kaman vaihtossa simuloidaan että oltaisiin laskettu irti käyttönäppäimestä.
272        if (player.ActiveItem != null)
273        {
274            player.ActiveItem.UseKeyReleased();
275        }
276
277        player.CycleItems();
278        UpdateItemCycleImages();
279    }
280
281    void UpdateItemCycleImages()
282    {
283        if (player.PrevItem != null) prevItem.Image = player.PrevItem.InventoryImage;
284        if (player.NextItem != null) nextItem.Image = player.NextItem.InventoryImage;
285        if (player.ActiveItem != null) currentItem.Image = player.ActiveItem.InventoryImage;
286
287        if (player.Sword != null)
288        {
289            swordFrame.Image = BigSwordImage;
290        }
291    }
292
293    ///// <summary>
294    ///// Luo pelaajan.
295    ///// </summary>
296    //void CreatePlayer(Vector position)
297    //{
298    //    player = new Creature(TILE_SIZE, TILE_SIZE);
299    //    player.MovementSpeed = 2300;
300    //    player.Position = position;
301    //    Add(player);
302
303    //    AddCollisionHandler(player, "exit", CollidesWithExit);
304    //}
305
306    void CollidesWithExit(PhysicsObject pPlayer, PhysicsObject pExit)
307    {
308        var oldExit = pExit as Exit;
309        if (oldExit == null || transition)
310            return;
311
312        transition = true;
313
314        // Otetaan vanhat objektit talteen.
315        oldObjects.Clear();
316        foreach (var obj in GetObjects(o => o != player))
317        {
318            if (obj != player)
319            {
320                oldObjects.Add(obj);
321            }
322        }
323
324        // Luodaan seuraava kenttä.
325        exits.Clear();
326        CreateLevel(oldExit.TargetLevel);
327
328        // Etsitään seuraavan kentän kohde exitti johon siirrytään.
329        var targetExit = exits.FirstOrDefault(e => e.Name == oldExit.TargetExitName);
330
331        // Jompikumpi uloskäynti ei ole kentän laidalla, sulava siirtyminen ei ole mahdollista.
332        if (GetExitDirection(targetExit) == Direction.None || GetExitDirection(oldExit) == Direction.None)
333        {
334            transition = false;
335            oldObjects.ForEach(o => o.Destroy());
336            oldObjects.Clear();
337
338            // Yritetään päätellä pelaajalle joku järkevä paikka.
339            player.Position = targetExit.Position + Direction.Inverse(targetExit.Position.Angle.MainDirection).GetVector() * TILE_SIZE * 2;
340            Camera.ZoomToLevel();
341            return;
342        }
343
344        // Pysäytetään peli siirtymän ajaksi.
345        Pause();
346        PhysicsEnabled = false;
347
348        // Lasketaan siirtymävektorit.
349        Direction dir = GetExitDirection(targetExit);
350        Vector exitDelta = targetExit.Position - oldExit.Position;
351        Vector transitionVector = Level.Size;
352        if (dir == Direction.Left || dir == Direction.Right)
353        {
354            transitionVector.X *= dir.GetVector().X;
355            transitionVector.Y = exitDelta.Y;
356        }
357        else
358        {
359            transitionVector.Y *= dir.GetVector().Y;
360            transitionVector.X = exitDelta.X;
361        }
362
363        // Siirretään vanhoja objekteja ja pelaajaa.
364        foreach (var obj in oldObjects)
365        {
366            obj.Position += transitionVector;
367        }
368        player.Position += transitionVector + Direction.Inverse(dir).GetVector() * TILE_SIZE * 4;
369
370        // Zoomataan kameraa sopivasti ja liikutetaan se vanhan kentän päälle, josta se sitten siirtyy uuden kentän päälle.
371        Camera.Position += transitionVector;
372        Vector pos = Camera.Position;
373        Camera.ZoomToLevel();
374        Camera.Position = pos;
375    }
376
377    /// <summary>
378    /// Palauttaa suunnan millä puolella kenttää uloskäynti on.
379    /// </summary>   
380    Direction GetExitDirection(Exit exit)
381    {
382        const double epsilon = 1e-3;
383        Func<double, double, bool> isSame = (x, y) => Math.Abs(y - x) < epsilon;
384
385        if (isSame(exit.Top, Level.Top))
386        {
387            return Direction.Up;
388        }
389        if (isSame(exit.Bottom, Level.Bottom))
390        {
391            return Direction.Down;
392        }
393        if (isSame(exit.Left, Level.Left))
394        {
395            return Direction.Left;
396        }
397        if (isSame(exit.Right, Level.Right))
398        {
399            return Direction.Right;
400        }
401        return Direction.None;
402    }
403
404    protected override void PausedUpdate(Time gameTime)
405    {
406        base.PausedUpdate(gameTime);
407        double dt = gameTime.SinceLastUpdate.TotalSeconds;
408
409        const double transitionSpeed = 500.0;
410
411        if (transition && !viewing)
412        {
413            Camera.Position += Camera.Position.Normalize() * -transitionSpeed * dt;
414
415            // Siirtymä on ohi, jatketaan peliä ja poistetaan edellinen kenttä.
416            if (Camera.Position.Magnitude < transitionSpeed * dt)
417            {
418                transition = false;
419                Pause();
420                PhysicsEnabled = true;
421                Camera.Position = Vector.Zero;
422
423                foreach (var obj in oldObjects)
424                {
425                    obj.Destroy();
426                }
427                oldObjects.Clear();
428            }
429        }
430
431        if(viewing && !transition)  //!transition perhaps being somewhat unnecessary, but now I do feel a bit safer.
432        {
433            second += dt;
434            if(second > 1)
435            {
436                if (messagesviewed.Count < 1)   //The letter's read, we better head back.
437                {
438                    Level.AmbientLight = 1;
439                    frame.Destroy();
440                    GetObjectsWithTag("labelWaitingToDie").ForEach(g => g.Destroy());
441                    viewing = false;
442                    Pause();
443                    return;
444                }
445
446                second = 0;
447                var storyLabel = new Label(messagesviewed.Dequeue()) { TextColor = Color.White };
448                storyLabel.Y = -midpoint + storyLabel.Height * messagesviewed.Count() + 1;
449                storyLabel.Tag = "labelWaitingToDie";
450                Add(storyLabel);
451
452            }
453            //Timer textTimer = new Timer();
454            //textTimer.Interval = 1;
455            //textTimer.Timeout += delegate
456            //{
457            //    if (messages.Count < 1)
458            //    {
459            //        Keyboard.EnableAll();
460            //        Level.AmbientLight = 1;
461            //        frame.Destroy();
462            //        GetObjectsWithTag("labelWaitingToDie").ForEach(g => g.Destroy());
463            //        textTimer.Stop();
464            //        Pause();
465            //        return;
466            //    }
467
468            //    var storyLabel = new Label(messages.Dequeue()) { TextColor = Color.White };
469            //    storyLabel.Y = -midpoint + storyLabel.Height * messages.Count() + 1;
470            //    storyLabel.Tag = "labelWaitingToDie";
471            //    Add(storyLabel);
472            //};
473            //textTimer.Start();
474        }
475    }
476
477    protected override void Update(Time time)
478    {
479        player.UpdateCreature(time);
480        base.Update(time);
481    }
482}
Note: See TracBrowser for help on using the repository browser.