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

Revision 6619, 14.3 KB checked in by sieerinn, 8 years ago (diff)

Aktiivisen kaman vaihto toimii.

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