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

Revision 6621, 14.7 KB checked in by sieerinn, 4 years ago (diff)

Kamanäppäimiä voi nyt hakata villisti ja peli ei kaatua.

RevLine 
[6536]1using System;
2using System.Collections.Generic;
[6539]3using System.Linq;
[6545]4using System.Reflection;
[6536]5using Jypeli;
6using Jypeli.Assets;
7using Jypeli.Controls;
8using Jypeli.Effects;
9using Jypeli.Widgets;
10
[6618]11public class StoryItem
12{
13    // Iso kuvake joka näkyy inventoryssä.
14    public Image InventoryImage { get; set; }
[6539]15
[6618]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
[6536]25public partial class TheLegendOfGabriel : PhysicsGame
26{
[6538]27    public const int TILE_SIZE = 20;
28
[6548]29    private Player player;
[6538]30
[6542]31    private bool transition;
[6539]32    List<GameObject> oldObjects = new List<GameObject>();
33    List<Exit> exits = new List<Exit>();
34
[6616]35    private bool viewing;
36    private double midpoint;
37    private double second;
38    GameObject frame;
39    Queue<string> messagesviewed;
40
[6618]41    private const int STORYITEM_COUNT = 3;
42    StoryItem[] storyItem = new StoryItem[3];
43
[6619]44    private Label currentItem;
45    private Label nextItem;
46    private Label prevItem;
47
[6545]48    #region Resources
49
[6549]50    public static Image GunImage = LoadImage("gun");
[6616]51    public static Image LetterImage = LoadImage("letter");
[6549]52    public static Image SmallSwordImage = LoadImage("smallsword");
[6619]53    public static Image MonocleImage = LoadImage("monocle");
[6549]54
[6618]55    public static Image FrameImage = LoadImage("frame");
56
[6545]57    [AssetName("walkright")]
[6547]58    internal Animation playerWalkRight;
[6545]59    [AssetName("walkright", mirror: true)]
[6547]60    internal Animation playerWalkLeft;
[6546]61    [AssetName("walkup")]
62    private Animation playerWalkUp;
63    [AssetName("walkdown")]
64    private Animation playerWalkDown;
[6545]65
[6548]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
[6617]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
[6545]84    #endregion
85
[6548]86    public override void Begin()
[6536]87    {
[6618]88        Mouse.IsCursorVisible = true;
[6536]89        SmoothTextures = false;
[6545]90        LoadAnimations();
[6536]91        StartGame();
[6619]92        //Intro();
[6618]93        BuildRightBar();
[6619]94        BuildInventoryCycle();
95        UpdateItemCycleImages();
[6536]96    }
97
[6620]98void BuildInventoryCycle()
[6619]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
[6618]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    }
[6545]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
[6616]155    void Intro()
156    {
[6618]157        storyItem[0] = new StoryItem(new Queue<string>(new[] { "Dear Alexander,", 
[6616]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" 
[6618]170        }), LetterImage);
171
172        ShowTextItem(storyItem[0]);
[6616]173    }
174
[6618]175    void ShowTextItem(StoryItem item)
[6616]176    {
177        viewing = true;
[6618]178        messagesviewed = new Queue<string>(item.Message);
[6616]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
[6618]189        midpoint = 26 * item.Message.Count() * 0.5;
[6616]190
191    }
192
[6545]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
[6536]201    private void StartGame()
202    {
203        ClearAll();
[6544]204        CreateLevel("level1");
[6548]205        //CreatePlayer(new Vector(-Level.Width/3, Level.Bottom + TILE_SIZE * 2));
[6536]206        SetControls();
207        Camera.ZoomToLevel();
208    }
209
210    void SetControls()
211    {
[6538]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
[6621]217        Keyboard.Listen(Key.X, ButtonState.Pressed, delegate { UseItem(player.ActiveItem, player.Sword, () => player.ActiveItem.UseKeyPressed()); }, null);
218        Keyboard.Listen(Key.X, ButtonState.Released, delegate { UseItem(player.ActiveItem, player.Sword, () => player.ActiveItem.UseKeyReleased()); }, null);
219        Keyboard.Listen(Key.X, ButtonState.Down, delegate { UseItem(player.ActiveItem, player.Sword, () => player.ActiveItem.UseKeyDown()); }, null);
[6548]220
[6621]221        Keyboard.Listen(Key.Z, ButtonState.Pressed, delegate { UseItem(player.Sword, player.ActiveItem, () => player.Sword.UseKeyPressed()); }, null);
222        Keyboard.Listen(Key.Z, ButtonState.Released, delegate { UseItem(player.Sword, player.ActiveItem, () => player.Sword.UseKeyReleased()); }, null);
223        Keyboard.Listen(Key.Z, ButtonState.Down, delegate { UseItem(player.Sword, player.ActiveItem, () => player.Sword.UseKeyDown()); }, null);
[6619]224
225        Keyboard.Listen(Key.Space, ButtonState.Pressed, delegate { player.CycleItems(); UpdateItemCycleImages(); }, null);
226
[6536]227        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, null);
228    }
[6539]229
[6621]230    void UseItem(Item item, Item otherItem, Action action)
231    {
232        bool inUse = false;
233        if (otherItem != null)
234        {
235            inUse = otherItem.InUse;
236        }
237
238        if (item != null && !inUse)
239        {
240            action();
241        }
242    }
243
[6619]244    void UpdateItemCycleImages()
245    {
246        if (player.PrevItem != null) prevItem.Image = player.PrevItem.InventoryImage;
247        if (player.NextItem != null) nextItem.Image = player.NextItem.InventoryImage;
248        if (player.ActiveItem != null) currentItem.Image = player.ActiveItem.InventoryImage;
249    }
250
[6544]251    ///// <summary>
252    ///// Luo pelaajan.
253    ///// </summary>
254    //void CreatePlayer(Vector position)
255    //{
256    //    player = new Creature(TILE_SIZE, TILE_SIZE);
257    //    player.MovementSpeed = 2300;
258    //    player.Position = position;
259    //    Add(player);
[6539]260
[6544]261    //    AddCollisionHandler(player, "exit", CollidesWithExit);
262    //}
[6539]263
264    void CollidesWithExit(PhysicsObject pPlayer, PhysicsObject pExit)
265    {
266        var oldExit = pExit as Exit;
267        if (oldExit == null || transition)
268            return;
269
270        transition = true;
271
272        // Otetaan vanhat objektit talteen.
273        oldObjects.Clear();
274        foreach (var obj in GetObjects(o => o != player))
275        {
276            if (obj != player)
277            {
278                oldObjects.Add(obj);
279            }
280        }
281
282        // Luodaan seuraava kenttä.
283        exits.Clear();
284        CreateLevel(oldExit.TargetLevel);
285
[6541]286        // Etsitään seuraavan kentän kohde exitti johon siirrytään.
287        var targetExit = exits.FirstOrDefault(e => e.Name == oldExit.TargetExitName);
288
289        // Jompikumpi uloskäynti ei ole kentän laidalla, sulava siirtyminen ei ole mahdollista.
290        if (GetExitDirection(targetExit) == Direction.None || GetExitDirection(oldExit) == Direction.None)
291        {
292            transition = false;
293            oldObjects.ForEach(o => o.Destroy());
294            oldObjects.Clear();
295
296            // Yritetään päätellä pelaajalle joku järkevä paikka.
297            player.Position = targetExit.Position + Direction.Inverse(targetExit.Position.Angle.MainDirection).GetVector() * TILE_SIZE * 2;
298            Camera.ZoomToLevel();
299            return;
300        }
301
[6539]302        // Pysäytetään peli siirtymän ajaksi.
303        Pause();
304        PhysicsEnabled = false;
305
306        // Lasketaan siirtymävektorit.
307        Direction dir = GetExitDirection(targetExit);
308        Vector exitDelta = targetExit.Position - oldExit.Position;
309        Vector transitionVector = Level.Size;
310        if (dir == Direction.Left || dir == Direction.Right)
311        {
312            transitionVector.X *= dir.GetVector().X;
313            transitionVector.Y = exitDelta.Y;
314        }
315        else
316        {
317            transitionVector.Y *= dir.GetVector().Y;
318            transitionVector.X = exitDelta.X;
319        }
320
321        // Siirretään vanhoja objekteja ja pelaajaa.
322        foreach (var obj in oldObjects)
323        {
324            obj.Position += transitionVector;
325        }
326        player.Position += transitionVector + Direction.Inverse(dir).GetVector() * TILE_SIZE * 4;
327
328        // Zoomataan kameraa sopivasti ja liikutetaan se vanhan kentän päälle, josta se sitten siirtyy uuden kentän päälle.
329        Camera.Position += transitionVector;
330        Vector pos = Camera.Position;
331        Camera.ZoomToLevel();
332        Camera.Position = pos;
333    }
334
335    /// <summary>
336    /// Palauttaa suunnan millä puolella kenttää uloskäynti on.
337    /// </summary>   
338    Direction GetExitDirection(Exit exit)
339    {
340        const double epsilon = 1e-3;
341        Func<double, double, bool> isSame = (x, y) => Math.Abs(y - x) < epsilon;
[6541]342
[6539]343        if (isSame(exit.Top, Level.Top))
344        {
345            return Direction.Up;
346        }
347        if (isSame(exit.Bottom, Level.Bottom))
348        {
349            return Direction.Down;
350        }
351        if (isSame(exit.Left, Level.Left))
352        {
353            return Direction.Left;
354        }
355        if (isSame(exit.Right, Level.Right))
356        {
357            return Direction.Right;
358        }
359        return Direction.None;
360    }
361
362    protected override void PausedUpdate(Time gameTime)
363    {
364        base.PausedUpdate(gameTime);
365        double dt = gameTime.SinceLastUpdate.TotalSeconds;
366
[6542]367        const double transitionSpeed = 500.0;
[6539]368
[6616]369        if (transition && !viewing)
[6539]370        {
[6542]371            Camera.Position += Camera.Position.Normalize() * -transitionSpeed * dt;
[6539]372
373            // Siirtymä on ohi, jatketaan peliä ja poistetaan edellinen kenttä.
[6542]374            if (Camera.Position.Magnitude < transitionSpeed * dt)
[6539]375            {
376                transition = false;
377                Pause();
378                PhysicsEnabled = true;
379                Camera.Position = Vector.Zero;
380
381                foreach (var obj in oldObjects)
382                {
383                    obj.Destroy();
384                }
385                oldObjects.Clear();
386            }
387        }
[6616]388
389        if(viewing && !transition)  //!transition perhaps being somewhat unnecessary, but now I do feel a bit safer.
390        {
391            second += dt;
392            if(second > 1)
393            {
394                if (messagesviewed.Count < 1)   //The letter's read, we better head back.
395                {
396                    Level.AmbientLight = 1;
397                    frame.Destroy();
398                    GetObjectsWithTag("labelWaitingToDie").ForEach(g => g.Destroy());
399                    viewing = false;
400                    Pause();
401                    return;
402                }
403
404                second = 0;
405                var storyLabel = new Label(messagesviewed.Dequeue()) { TextColor = Color.White };
406                storyLabel.Y = -midpoint + storyLabel.Height * messagesviewed.Count() + 1;
407                storyLabel.Tag = "labelWaitingToDie";
408                Add(storyLabel);
409
410            }
411            //Timer textTimer = new Timer();
412            //textTimer.Interval = 1;
413            //textTimer.Timeout += delegate
414            //{
415            //    if (messages.Count < 1)
416            //    {
417            //        Keyboard.EnableAll();
418            //        Level.AmbientLight = 1;
419            //        frame.Destroy();
420            //        GetObjectsWithTag("labelWaitingToDie").ForEach(g => g.Destroy());
421            //        textTimer.Stop();
422            //        Pause();
423            //        return;
424            //    }
425
426            //    var storyLabel = new Label(messages.Dequeue()) { TextColor = Color.White };
427            //    storyLabel.Y = -midpoint + storyLabel.Height * messages.Count() + 1;
428            //    storyLabel.Tag = "labelWaitingToDie";
429            //    Add(storyLabel);
430            //};
431            //textTimer.Start();
432        }
[6539]433    }
[6546]434
435    protected override void Update(Time time)
436    {
[6548]437        player.UpdateCreature(time);
[6546]438        base.Update(time);
439    }
[6536]440}
Note: See TracBrowser for help on using the repository browser.