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

Revision 6620, 14.3 KB checked in by empaheik, 8 years ago (diff)

Lel.

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