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

Revision 6287, 27.3 KB checked in by sieerinn, 5 years ago (diff)

Noitaa jatkettu.

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