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

Revision 6631, 17.5 KB checked in by sieerinn, 4 years ago (diff)

Miekan ääntä säädetty hiljaisemmaksi. Kranaatteja voi heitellä.

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