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

Revision 6293, 29.9 KB checked in by empaheik, 5 years ago (diff)

Vähän haastavampi tulimaagi, uudelleenpoimittava maitokannu.

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