source: 2015/26/ohjaajat/HillbillyRun/HillbillyRun/HillbillyRun/HillbillyRun/HillbillyRun.cs @ 6288

Revision 6288, 27.6 KB checked in by sieerinn, 5 years ago (diff)

F12-näppäimellä siirtyy seuraavaan kenttään.

Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using Jypeli;
5using Jypeli.Assets;
6using Jypeli.Controls;
7using Jypeli.Effects;
8using Jypeli.Widgets;
9
10/* Muistutuksia.
11 *
12 * Layerit
13 *   3 -
14 *   2 -
15 *   1 -
16 *   0 -
17 *  -1 - Näkyvä maanpinta.
18 *  -2 - Talot taustalla.
19 * 
20 * CollisionIgnoreGroupit
21 *  3 - Ryömivät ja liekit. //TODO: lisätä noidatkin tänne
22 *  2 - Kärry.
23 *
24*/
25
26#region Improvement
27public abstract class Improvement : PlatformCharacter
28{
29    public List<Animation> Animations { get; set; }
30
31    protected Improvement(double width, double height)
32        : base(width, height)
33    {
34
35    }
36
37    public HillBilly Owner
38    {
39        get { return owner; }
40        set { owner = value; }
41    }
42    private HillBilly owner;
43
44    public virtual void DoTheThing() { }
45}
46
47//Luokka maajussien erikoisuuksille.
48public class MilkImprovement : Improvement
49{
50
51
52    public override void DoTheThing()
53    {
54        HillbillyRun game = this.Game as HillbillyRun;
55        game.CreateMilkParticles(this.Owner);
56    }
57
58    public MilkImprovement(double width, double height)
59        : base(width, height)
60    {
61
62    }
63}
64
65#endregion
66
67public class HillBilly : PlatformCharacter
68{
69    private IntMeter lifeCounter = new IntMeter(4, 0, 4);
70    public IntMeter Life
71    {
72        set { lifeCounter = value; }
73        get { return lifeCounter; }
74    }
75
76    public Improvement Improvement { get; set; }
77
78    public void GainImprovement(Improvement improvement)
79    {
80        this.AnimWalk = improvement.Animations[0];
81        this.AnimIdle = new Animation(improvement.Animations[0].CurrentFrame);
82        this.Improvement = improvement;
83        improvement.Owner = this;
84
85        improvement.Destroy();
86    }
87
88    public void UseImprovement(Improvement improvement)
89    {
90        if (Animation != improvement.Animations[1])
91        {
92            this.PlayAnimation(improvement.Animations[1], improvement.DoTheThing);
93        }
94    }
95
96    public HillBilly(double leveys, double korkeus)
97        : base(leveys, korkeus)
98    {
99
100    }
101}
102
103/// <summary>
104/// An MMO where you go to war with mages in the lava kingdom.
105/// </summary>
106public class HillbillyRun : PhysicsGame
107{
108    private List<HillBilly> players = new List<HillBilly>();
109    private List<HillBilly> startingPlayers = new List<HillBilly>();
110
111    //private List<double> playerPositionsX = new List<double>();
112    //private List<double> playerPositionsY = new List<double>();
113
114    private const double PLAYER_SPEED = 180;
115    public const double TILE_SIZE = 70;
116
117    private double cameraTargetX; // Sijainti jossa kameran pitäisi olla.
118    private Vector cameraTarget;
119
120    private double cameraOffset; //= 400; // TODO: Tämän voisi ehkä laskea jostain (esim. ikkunan leveydestä kolmasosa tai jotain).
121    private double cameraSpeed = 2.0; // Kameran liikkumisnopeus.
122
123    # region Images
124    private Image[] groundImages = LoadImages("ground", "ground");    //Näitä ei tosin kaikkia kenties jaksa tehdä erilaisiksi levelistä riippuen
125    private Image[] groundTopImages = LoadImages("ground_top", "ground_top");
126    private Image[] foregroundDecorations = LoadImages("viljaa", "grass");
127    private Image[] blockImages = LoadImages("box2", "box");
128
129    private Image[] houseImages = LoadImages("house", "houseburned");
130
131    private Image cartImage = LoadImage("cart");
132    private Image milkImage = LoadImage("tonkkaitem");
133
134    private Image cartWheelImage = LoadImage("cartwheel");
135
136    private Image smokeImage1 = LoadImage("smoke1");
137    private Image smokeImage2 = LoadImage("smoke2");
138
139    private Image forestBackgroundImage = LoadImage("forestbackground");
140
141    private Animation crawl;
142    private Animation blaze;
143
144    private Animation pitchforkAttack;
145    private Animation pitchforkWalk;
146    private Animation milkThrow;
147    private Animation milkWalk;
148    private Animation normalWalk;
149    private Animation playerIdle;
150    private Animation playerJump;
151    private Animation playerFall;
152    private Animation firemageAnimation;
153    private Animation firemageCastAnimation;
154    #endregion
155
156    private double leftCamLimit;
157    private double rightCamLimit;
158    private double bottomCamLimit;
159
160    private int levelNumber = 0;
161
162    public override void Begin()
163    {
164        Initializing();
165        //IntroSequence();
166        //MainMenu();
167        StartGame();
168    }
169
170    #region Intro
171    void IntroSequence()
172    {
173        Level.Background.Color = Color.Black;
174
175        Keyboard.Listen(Key.Escape, ButtonState.Pressed, SkipIntro, "Skip");
176
177        ShowMadeWithJypeli();
178
179        Timer.SingleShot(4.0, delegate // TODO get rid of fixed amount of seconds
180        {
181            ShowBackgroundStory();
182        });
183
184
185
186    }
187
188    void ShowMadeWithJypeli()
189    {
190        Image madewithImage = LoadImage("madewithjypeli");
191
192        double w = Window.Width / 4;
193        double h = w * (madewithImage.Height / (double)madewithImage.Width); // take aspect ratio from the picture
194
195        GameObject madewithjypeliObject = new GameObject(w, h);
196        madewithjypeliObject.Image = madewithImage;
197        Add(madewithjypeliObject);
198
199        // Tässä oli jotain epätehokasta feidailua tuolle Made with Jypeli -kuvalle. Ei tunnu päivittyvän joka framella tai on muuten vain tosi raskas...
200
201        //fadeTimer = new Timer();
202        //fadeTimer.Interval = 0.5;
203        //fadeTimer.Timeout += delegate
204        //{
205        //    madewithjypeliObject.Image = LerpImage(madewithjypeliObject.Image, Color.Black, 0.6);
206        //};
207        //fadeTimer.Start(5);
208
209        Timer.SingleShot(1.2, delegate
210        {
211            madewithjypeliObject.Destroy();
212        });
213
214    }
215
216    Image LerpImage(Image original, Color targetColor, double ratio)
217    {
218        Image newImage = new Image(original.Width, original.Height, Color.Transparent);
219        for (int y = 0; y < original.Height; y++)
220        {
221            for (int x = 0; x < original.Width; x++)
222            {
223                newImage[y, x] = Color.Lerp(original[y, x], targetColor, ratio);
224            }
225        }
226        return newImage;
227    }
228
229    void ShowBackgroundStory()
230    {
231        ShowStoryText(new Queue<string>(new[] { "Once upon a time...", "...blaa blaa blaa.", "Blaa." }));
232    }
233
234    void ShowStoryText(Queue<string> messages)
235    {
236        // Mennään alkuvalikkoon jos ei ole enää viestejä.
237        if (messages.Count == 0)
238        {
239            MainMenu();
240            return;
241        }
242
243        // Näytetään nykyinen viesti.
244        var storyLabel = new Label(messages.Dequeue()) { TextColor = Color.Black, TextScale = new Vector(3, 3) };
245        Add(storyLabel);
246
247        var textTimer = new Timer { Interval = 0.05 };
248        textTimer.Timeout += () => storyLabel.TextColor = Color.Lerp(storyLabel.TextColor, Color.White, 0.05);
249        textTimer.Start();
250
251        // Näytetään seuraava viesti muutaman sekunnin päästä.
252        Timer.SingleShot(4, delegate { storyLabel.Destroy(); ShowStoryText(messages); });
253    }
254
255    void SkipIntro()
256    {
257        ClearTimers();
258        ClearAll();
259        Keyboard.Clear();
260        MainMenu();
261    }
262
263    void MainMenu()
264    {
265        Level.Background.Color = Color.DarkBlue;
266
267        MultiSelectWindow mainmenu = new MultiSelectWindow("Main menu",
268"Start game", "Credits", "Exit");
269        mainmenu.AddItemHandler(0, StartGame);
270        mainmenu.AddItemHandler(1, ShowCredits);
271        mainmenu.AddItemHandler(2, Exit);
272        mainmenu.DefaultCancel = 2;
273        Add(mainmenu);
274    }
275
276    void ShowCredits()
277    {
278        MessageWindow win = new MessageWindow("This game was made in one week by\nSimo Rinne,\nEmma Heikura,\n and Jouni Potila\n using University of Jyväskylä's\n game programming library Jypeli");
279        win.Closed += delegate
280        {
281            ClearAll();
282            MainMenu();
283        };
284        Add(win);
285    }
286    #endregion
287
288    void StartGame()
289    {
290        ClearAll();
291        CreateLevel();
292        ScreenSettings();
293        SetControls();
294    }
295
296    public void NextLevel()
297    {
298        levelNumber++;
299        StartGame();
300    }
301
302    void Initializing()
303    {
304        crawl = LoadAnimation("crawl");
305        blaze = LoadAnimation("flame");
306        pitchforkAttack = LoadAnimation("attack");
307        pitchforkWalk = LoadAnimation("hanko");
308        milkThrow = LoadAnimation("heitto");
309        milkWalk = LoadAnimation("tonkka");
310        normalWalk = LoadAnimation("pwalk");
311        playerIdle = LoadAnimation("idle");
312        playerJump = LoadAnimation("jump");
313        playerFall = LoadAnimation("fall");
314        firemageAnimation = LoadAnimation("firemage");
315        firemageCastAnimation = LoadAnimation("firemagecast");
316
317        cameraOffset = Window.Width / 4;
318    }
319
320    void ScreenSettings()
321    {
322        Window.Width = 1800;
323        Window.Height = 900;
324
325        leftCamLimit = Level.Left + Window.Width / 2.0;
326        rightCamLimit = Level.Right - Window.Width / 2.0;
327        bottomCamLimit = Level.Bottom + Window.Height / 2.0;
328
329        Camera.X = cameraTargetX = leftCamLimit;
330
331        Timer cameraTimer = new Timer();
332        cameraTimer.Interval = 1 / 30.0;
333        cameraTimer.Timeout += UpdateCamera;
334        cameraTimer.Start();
335
336        //Background
337        GameObject forestBackground = new GameObject(Level.Width, Level.Height);
338        forestBackground.Image = forestBackgroundImage;
339        forestBackground.TextureWrapSize = new Vector(5, 1);
340        Add(forestBackground, -3);
341        Layers[-3].RelativeTransition = new Vector(0.5, 1.0);
342        Level.Background.CreateGradient(Color.Black, Color.SkyBlue);
343    }
344
345    #region LevelCreation
346    void CreateLevel()
347    {
348        startingPlayers.Clear();
349        players.Clear();
350        Gravity = new Vector(0, -1000);
351
352        //Tilemap
353        ColorTileMap level = ColorTileMap.FromLevelAsset("level" + levelNumber);
354        level.SetTileMethod(Color.Black, CreateGroundTop);
355        level.SetTileMethod(Color.Brown, CreateGround);
356
357        level.SetTileMethod(Color.Cyan, CreateHouse);
358        level.SetTileMethod(Color.PaintDotNetBlue, CreateBurnedHouse);
359
360        level.SetTileMethod(Color.Gold, CreatePlayer);
361        level.SetTileMethod(Color.Harlequin, CreateCart);
362        level.SetTileMethod(Color.White, CreateBlockObject);
363        level.SetTileMethod(Color.DarkGray, CreateMilk);
364        level.SetTileMethod(Color.Gray, CreateCrawly);
365        level.SetTileMethod(Color.Red, CreateFireMage);
366        level.SetTileMethod(Color.Rose, CreateFlame);
367        //level.SetTileMethod(Color.Azure, CreateDummy, Color.Azure);   //TODO: CreateSmoke
368        //level.SetTileMethod(Color.Orange, CreateDummy, Color.Orange); //TODO: CreateTombstone
369        level.Optimize(Color.Black, Color.Brown);
370        level.Execute(TILE_SIZE, TILE_SIZE);
371    }
372
373    void CreateFlame(Vector position, double width, double height)
374    {
375        PhysicsObject flame = PhysicsObject.CreateStaticObject(width, height * 2);
376        //flame.Image = flameImage;
377        flame.Color = Color.Red;
378        double hieman = height * 0.3;
379        flame.Position = position - new Vector(0, hieman);
380        flame.CollisionIgnoreGroup = 3;
381        flame.Tag = "burn";
382        flame.Animation = new Animation(blaze) { FPS = RandomGen.NextInt(20, 26) };
383        flame.Animation.Step(RandomGen.NextInt(0, 12));
384        flame.Animation.Resume();
385        Add(flame);
386
387        Smoke savu = new Smoke();
388        savu.ParticleImage = smokeImage1;
389        savu.OuterParticleImage = smokeImage2;
390        savu.MaxLifetime = 1.0;
391        savu.MaxScale = 200;
392        savu.MinScale = 10;
393        savu.Position = flame.Position;
394        Wind = new Vector(-10, 0);
395        Add(savu);
396
397        AddCollisionHandler(flame, "milkparticle", delegate(PhysicsObject c, PhysicsObject particle)
398        {
399            particle.Destroy();
400            flame.Destroy();
401            savu.Destroy();
402        });
403    }
404
405    void CreateBlockObject(Vector position, double width, double height)
406    {
407        // Säädin vähän tätä jotta laatikko näkyy hyvin. Pitää ehkä tehdä laatikolle ihan oma metodi.
408        PhysicsObject block = PhysicsObject.CreateStaticObject(width, height);
409        block.IsVisible = false;
410        //block.Image = blockImages[levelNumber];
411        block.Position = position;
412        block.Y -= height / 2.0;
413        Add(block, 1);
414
415        GameObject visibleBlock = new GameObject(width, height * 1.5);
416        visibleBlock.Position = position;
417        visibleBlock.Image = blockImages[levelNumber];
418        visibleBlock.Y -= height / 2.0;
419        Add(visibleBlock, -1);
420    }
421
422    void CreateMilk(Vector position, double width, double height)
423    {
424        double size = 30;
425        double ratio = milkImage.Height / milkImage.Width;
426
427        Improvement milk = new MilkImprovement(size, size * ratio);
428        milk.Image = milkImage;
429        milk.Animations = new List<Animation> { milkWalk, milkThrow };
430        milk.Position = position;
431        milk.Tag = "milk";
432        Add(milk);
433
434        //PhysicsObject milk = new PhysicsObject(size, size * ratio);
435        //milk.Image = milkImage;
436        //milk.Position = position;
437        //milk.Tag = "milk";
438        //Add(milk);
439    }
440
441    void CreateCrawly(Vector position, double width, double height)
442    {
443        PlatformCharacter crawly = new PlatformCharacter(width * 2, height * 0.6);
444        crawly.Position = position;
445        crawly.Color = Color.Gray;
446        crawly.Animation = new Animation(crawl);
447        crawly.Animation.FPS = RandomGen.NextInt(18, 24);
448        crawly.Animation.Step(RandomGen.NextInt(0, 16));
449        crawly.Animation.Resume();
450        crawly.Tag = "burn";
451        crawly.CollisionIgnoreGroup = 3;
452        Add(crawly, 1);
453
454        GameObject flame = new GameObject(width * 1.4, height * 2);
455        flame.Animation = new Animation(blaze) { FPS = RandomGen.NextInt(20, 26) };
456        flame.Animation.Step(RandomGen.NextInt(0, 12));
457        flame.Animation.Resume();
458        Add(flame);
459
460        // Pakko liikutella näin koska lapsioliona liekki näkyisi ryömijän päällä.
461        Timer flameMover = new Timer { Interval = 0.05 };
462        flameMover.Timeout += delegate
463        {
464            double hieman = height * 0.75;
465            flame.Position = crawly.Position + new Vector(0, hieman);
466        };
467        flameMover.Start();
468
469        PlatformWandererBrain brain = new PlatformWandererBrain();
470        brain.Speed = 20;
471        brain.FallsOffPlatforms = true;
472
473        crawly.Brain = brain;
474
475        // Sammuu törmätessään maitoon.
476        AddCollisionHandler(crawly, "milkparticle", delegate(PhysicsObject c, PhysicsObject particle)
477        {
478            particle.Destroy();
479            crawly.Brain = null;
480            crawly.Animation = new Animation(crawly.Animation.CurrentFrame);
481            crawly.Tag = "";
482            flame.Destroy();
483            RemoveCollisionHandlers(crawly);
484        });
485    }
486
487    void CreateFireMage(Vector position, double width, double height)
488    {
489        PlatformCharacter mage = new PlatformCharacter(width * 3, height * 4);
490        mage.Position = position;
491        mage.Y += mage.Height / 2.0;
492        mage.Tag = "burn";
493        mage.AnimWalk = new Animation(firemageAnimation);
494        mage.CollisionIgnoreGroup = 3;
495        Add(mage, 1);
496
497        // Pään päällä oleva liekki (taitaa olla vähän huonossa kohtaa tällä hetkellä)
498        GameObject flame = new GameObject(width * 1.4, height * 2);
499        flame.Y += mage.Height * 0.65;
500        flame.Animation = new Animation(blaze);
501        flame.Animation.Start();
502        mage.Add(flame);
503
504        PlatformWandererBrain brain = new PlatformWandererBrain();
505        brain.Speed = 20;
506        brain.FallsOffPlatforms = false;
507        mage.Brain = brain;
508
509        // TODO: Noita kuolee kun on loiskuteltu tarpeeksi maitoa sen päälle. Vain yläpuolelta tulevat maitopartikkelit vahingoittaa sitä.
510
511        // TODO: Tulta pitäisi taikoa vain kun pelaajat on lähellä.
512
513        // Taiotaan tulta välillä.
514        var castTimer = new Timer { Interval = 10.0 };
515        castTimer.Timeout += delegate
516        {
517            // TODO: Kävelyanimaatio pysähtyy jostain syystä tämän animaation jälkeen.
518            mage.PlayAnimation(firemageCastAnimation);
519
520            for (int i = 0; i < 6; i++)
521            {
522                PhysicsObject fire = new PhysicsObject(30, 60);
523                fire.CanRotate = false;
524                fire.Tag = "fire";
525                fire.Animation = new Animation(blaze) { FPS = RandomGen.NextInt(20, 26) };
526                fire.Animation.Step(RandomGen.NextInt(0, 12));
527                fire.Animation.Resume();
528                fire.X = mage.X + RandomGen.NextDouble(-300, 300);
529                fire.Y = mage.Y + mage.Height * 1.5;
530                fire.CollisionIgnoreGroup = 3;
531                Add(fire);
532
533                AddCollisionHandler(fire, "milkparticle", delegate(PhysicsObject c, PhysicsObject particle)
534                {
535                    particle.Destroy();
536                    fire.Destroy();
537                });
538            }
539        };
540        castTimer.Start();
541    }
542
543    void CreateHouse(Vector position, double width, double height)
544    {
545        // Näkyvä talo
546        GameObject house = new GameObject(width * 10, height * 8);
547        house.Image = houseImages[0];
548        house.Position = position - new Vector(0, height * 2.5);
549        Add(house, -2);
550
551        //Seisottava tasanne
552        PhysicsObject platform = PhysicsObject.CreateStaticObject(house.Width - (TILE_SIZE * 3.25), 1);     //Tätä kohtaa on nyt vähän hakemalla haettu.
553        platform.IsVisible = false;
554        platform.Position = new Vector(house.X + (TILE_SIZE * 0.5), house.Top);
555        Add(platform);
556    }
557
558    void CreateBurnedHouse(Vector position, double width, double height)
559    {
560        GameObject house = new GameObject(width * 10, height * 8);
561        house.Image = houseImages[1];
562        house.Position = position - new Vector(0, height * 2.5);
563        Add(house, -2);
564
565        PhysicsObject platform = PhysicsObject.CreateStaticObject(house.Width * 0.25, 1);
566        platform.IsVisible = false;
567        platform.Position = new Vector(house.X + platform.Width * 0.5, house.Top);
568        Add(platform);
569    }
570
571    private void CreateCart(Vector position, double width, double height)
572    {
573        double size = 0.7;
574        PhysicsObject cart = new PhysicsObject(400 * size, 80 * size);
575        cart.Position = position;
576        cart.Image = cartImage;
577        cart.CollisionIgnoreGroup = 2;
578        Add(cart);
579        PhysicsObject cartWheel = new PhysicsObject(160 * size, 160 * size, Shape.Circle);
580        cartWheel.Image = cartWheelImage;
581        cartWheel.Position = cart.Position + new Vector(-110, -30) * size;
582        cartWheel.CollisionIgnoreGroup = 2;
583        Add(cartWheel);
584        AxleJoint joint = new AxleJoint(cart, cartWheel);
585        Add(joint);
586    }
587
588    private void CreateDummy(Vector position, double width, double height, Color color)
589    {
590        PhysicsObject dummy = PhysicsObject.CreateStaticObject(width, height);
591        dummy.Position = position;
592        dummy.Color = color;
593        Add(dummy);
594    }
595
596    void CreatePlayer(Vector position, double width, double height)
597    {
598        HillBilly player = new HillBilly(width, height * 2);
599        player.Shape = Shape.Rectangle;
600        player.Position = position + new Vector(0, height * 0.5);
601        player.Color = Color.White;
602        player.AnimWalk = new Animation(normalWalk);
603        player.AnimIdle = new Animation(playerIdle);
604        player.AnimJump = new Animation(playerJump);
605        player.AnimFall = new Animation(playerFall);
606        player.AnimFall.StopOnLastFrame = true;
607        players.Add(player);
608        startingPlayers.Add(player);
609        Add(player);
610        AddCollisionHandler(player, "burn", delegate(PhysicsObject p, PhysicsObject t)
611        {
612            HillBilly billy = p as HillBilly;
613            billy.Life.Value--;
614
615        });
616
617        player.Life.LowerLimit += delegate
618        {
619            if (players.Count < 2)
620            {
621                Loss();
622            }
623            else { players.Remove(player); player.Destroy(); }
624        };
625
626        AddCollisionHandler(player, "milk", CollectMilk);
627    }
628
629    void CreateGroundTop(Vector position, double width, double height)
630    {
631        // Puolet pienempi näkymätön palikka alla johon törmää.
632        PhysicsObject ground = PhysicsObject.CreateStaticObject(width, height / 2.0);
633        ground.IsVisible = false;
634        ground.Position = position - new Vector(0.0, TILE_SIZE / 4.0);
635        Add(ground);
636
637        // Maanpinnan näkyvä osa.
638        GameObject visibleGround = new GameObject(width, height);
639        visibleGround.Image = groundImages[levelNumber];
640        visibleGround.Position = position;
641        visibleGround.TextureWrapSize = new Vector(width / TILE_SIZE, height / TILE_SIZE);
642        Add(visibleGround, -1);
643
644        int probability = RandomGen.NextInt(100);
645        bool wheat = probability < 20;
646
647        if (wheat)
648        {
649            GameObject wheatBlock = new GameObject(width * 1.5, height * 2);
650            wheatBlock.Image = foregroundDecorations[0];
651            wheatBlock.X = visibleGround.X;
652            wheatBlock.Bottom = visibleGround.Bottom;
653            wheatBlock.TextureWrapSize = new Vector(width / TILE_SIZE, height / TILE_SIZE);
654            Add(wheatBlock, 2);
655        }
656    }
657
658    void CreateGround(Vector position, double width, double height)
659    {
660        PhysicsObject ground = PhysicsObject.CreateStaticObject(width, height);
661        ground.Image = groundTopImages[levelNumber];
662        ground.Position = position;
663        ground.TextureWrapSize = new Vector(width / TILE_SIZE, height / TILE_SIZE);
664        Add(ground);
665    }
666    #endregion
667
668    void SetControls()
669    {
670        Keyboard.Listen(Key.A, ButtonState.Down, delegate { startingPlayers[0].Walk(-PLAYER_SPEED); }, "Player 1 moves left");
671        Keyboard.Listen(Key.D, ButtonState.Down, delegate { startingPlayers[0].Walk(PLAYER_SPEED); }, "Player 1 moves right");
672        Keyboard.Listen(Key.W, ButtonState.Down, delegate { startingPlayers[0].Jump(PLAYER_SPEED * 2); }, "Player 1 jumps");    //Just PLAYER_SPEED felt alright as well
673        Keyboard.Listen(Key.E, ButtonState.Pressed, UseImprovement, "Player 1 uses their tools", startingPlayers[0]);
674
675        Keyboard.Listen(Key.Left, ButtonState.Down, delegate { startingPlayers[1].Walk(-PLAYER_SPEED); }, "Player 2 moves left");
676        Keyboard.Listen(Key.Right, ButtonState.Down, delegate { startingPlayers[1].Walk(PLAYER_SPEED); }, "Player 2 moves right");
677        Keyboard.Listen(Key.Up, ButtonState.Down, delegate { startingPlayers[1].Jump(PLAYER_SPEED * 2); }, "Player 2 jumps");
678        Keyboard.Listen(Key.RightShift, ButtonState.Pressed, UseImprovement, "Player 2 uses their tools", startingPlayers[1]);
679
680        Keyboard.Listen(Key.F12, ButtonState.Pressed, NextLevel, null);
681
682        Keyboard.Listen(Key.F1, ButtonState.Pressed, ShowControlHelp, "Show help");
683        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, "Exit game");
684    }
685
686    public void CreateMilkParticles(HillBilly billy)
687    {
688        for (int i = 0; i < 10; i++)
689        {
690            const double maxLife = 1.0;
691            PhysicsObject milkParticle = new PhysicsObject(10, 10, Shape.Circle);
692            milkParticle.Color = new Color(255, 255, 255, 128);
693            milkParticle.Position = billy.Position + new Vector(0, -30);
694            milkParticle.IgnoresCollisionResponse = true;
695            milkParticle.Tag = "milkparticle";
696            milkParticle.LifetimeLeft = TimeSpan.FromSeconds(maxLife);
697            Add(milkParticle);
698
699            // Väri muuttuu läpinäkyväksi.
700            var fadeTimer = new Timer { Interval = 0.05 };
701            fadeTimer.Timeout += delegate
702            {
703                byte c = 255;
704                milkParticle.Color = new Color(c, c, c, (byte)(128 * milkParticle.LifetimeLeft.TotalSeconds / maxLife));
705            };
706            fadeTimer.Start();
707            milkParticle.Destroyed += fadeTimer.Stop;
708
709            // Random lentonopeus.
710            var rx = RandomGen.NextDouble(-50, 50);
711            var ry = RandomGen.NextDouble(-50, 50);
712            milkParticle.Hit(new Vector(billy.FacingDirection.GetVector().X * (200 + rx), 300 + ry));
713        }
714    }
715
716    private void UseImprovement(HillBilly player)
717    {
718        if (player.Improvement == null)
719        {
720            player.Jump(200);   //TODO: CRY ALL THE TEARS  :'(
721            return;
722        }
723
724        player.UseImprovement(player.Improvement);
725    }
726
727    void Loss()
728    {
729        //TODO: Sumthin' flashy for our fallen friends.
730        Exit();
731    }
732
733    void CollectMilk(PhysicsObject player, PhysicsObject milk)
734    {
735        HillBilly billy = player as HillBilly;
736        if (billy == null)
737            return;
738
739        Improvement milkI = milk as Improvement;
740        billy.GainImprovement(milkI);
741
742        milk.Destroy();
743        //billy.AnimWalk = new Animation(milkWalk);
744        //billy.AnimIdle = new Animation(milkWalk.CurrentFrame);
745    }
746
747    #region Camera
748    void UpdateCamera()
749    {
750        double minY = players.Min(p => p.Y);
751        double maxY = players.Max(p => p.Y);
752        double minX = players.Min(p => p.X) + cameraOffset;
753
754        Vector minPosition = new Vector(Math.Max(minX, cameraTargetX), minY);
755        Vector maxPosition = new Vector(minX, maxY);
756
757        cameraTarget = (minPosition + maxPosition) * 0.5;
758        cameraTarget.X = Math.Max(cameraTargetX, minX);     //Lellllll.
759
760        //cameraTarget.Y = Math.Max(cameraTarget.X, Level.Bottom + Window.Height/2.0);
761
762        cameraTargetX = Math.Max(cameraTargetX, minX);
763
764        cameraTarget.X = Math.Min(cameraTargetX, rightCamLimit);
765        cameraTarget.Y = Math.Max(cameraTarget.Y, bottomCamLimit);
766
767        double windowMax = Camera.ScreenToWorld(new Vector(Window.Width / 2.0, 0)).X;
768        double windowMin = Camera.ScreenToWorld(new Vector(-Window.Width / 2.0, 0)).X;
769        foreach (var player in players)
770        {
771            player.Left = Math.Max(player.Left, windowMin);
772            player.Right = Math.Min(player.Right, windowMax);
773        }
774    }
775
776    protected override void Update(Time time)
777    {
778        Camera.Position += (cameraTarget - Camera.Position) * time.SinceLastUpdate.TotalSeconds * cameraSpeed;
779        //Camera.X += (cameraTargetX - Camera.X) * time.SinceLastUpdate.TotalSeconds * cameraSpeed;
780
781
782        base.Update(time);
783    }
784
785    /// <summary>
786    /// Yritän leikkiä kameralla. Vielä varmaan hetken pidempään.
787    /// </summary>
788    /// <param name="gameTime"></param>
789    /*
790    protected override void Update(Microsoft.Xna.Framework.GameTime gameTime)
791    {
792        foreach(HillBilly player in players)
793        {
794            playerPositionsX.Add(player.Position.X);
795            playerPositionsY.Add(player.Position.Y);
796        }
797
798        double maxX = playerPositionsX.Max();
799        double maxY = playerPositionsY.Max();
800        double minX = playerPositionsX.Min();
801        double minY = playerPositionsY.Min();
802
803        Vector minPosition = new Vector(minX, minY);
804        Vector maxPosition = new Vector(maxX, maxY);
805
806        Camera.Position = (minPosition + maxPosition) * 0.5;
807
808        playerPositionsX.Clear();
809        playerPositionsY.Clear();
810
811        base.Update(gameTime);
812    }
813     */
814    #endregion
815}
Note: See TracBrowser for help on using the repository browser.