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

Revision 6291, 29.3 KB checked in by empaheik, 5 years ago (diff)

Tapettava tulimaagi + liekit, joiden läpi voi kävellä + liekkien tekeminen (kenties tarpeettomasti) sovitettuna vain yhteen aliohjelmaan.

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);
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           
411                savu.Destroy();
412           
413        });
414    }
415
416    void CreateBlockObject(Vector position, double width, double height)
417    {
418        // Säädin vähän tätä jotta laatikko näkyy hyvin. Pitää ehkä tehdä laatikolle ihan oma metodi.
419        PhysicsObject block = PhysicsObject.CreateStaticObject(width, height);
420        block.IsVisible = false;
421        //block.Image = blockImages[levelNumber];
422        block.Position = position;
423        block.Y -= height / 2.0;
424        Add(block, 1);
425
426        GameObject visibleBlock = new GameObject(width, height * 1.5);
427        visibleBlock.Position = position;
428        visibleBlock.Image = blockImages[levelNumber];
429        visibleBlock.Y -= height / 2.0;
430        Add(visibleBlock, -1);
431    }
432
433    void CreateMilk(Vector position, double width, double height)
434    {
435        double size = 30;
436        double ratio = milkImage.Height / milkImage.Width;
437
438        Improvement milk = new MilkImprovement(size, size * ratio);
439        milk.Image = milkImage;
440        milk.Animations = new List<Animation> { milkWalk, milkThrow };
441        milk.Position = position;
442        milk.Tag = "milk";
443        Add(milk);
444
445        //PhysicsObject milk = new PhysicsObject(size, size * ratio);
446        //milk.Image = milkImage;
447        //milk.Position = position;
448        //milk.Tag = "milk";
449        //Add(milk);
450    }
451
452    void CreateCrawly(Vector position, double width, double height)
453    {
454        PlatformCharacter crawly = new PlatformCharacter(width * 2, height * 0.6);
455        crawly.Position = position;
456        crawly.Color = Color.Gray;
457        crawly.Animation = new Animation(crawl);
458        crawly.Animation.FPS = RandomGen.NextInt(18, 24);
459        crawly.Animation.Step(RandomGen.NextInt(0, 16));
460        crawly.Animation.Resume();
461        crawly.Tag = "burn";
462        crawly.CollisionIgnoreGroup = 3;
463        Add(crawly, 1);
464
465        GameObject flame = new GameObject(width * 1.4, height * 2);
466        flame.Animation = new Animation(blaze) { FPS = RandomGen.NextInt(20, 26) };
467        flame.Animation.Step(RandomGen.NextInt(0, 12));
468        flame.Animation.Resume();
469        Add(flame);
470
471        // Pakko liikutella näin koska lapsioliona liekki näkyisi ryömijän päällä.
472        Timer flameMover = new Timer { Interval = 0.05 };
473        flameMover.Timeout += delegate
474        {
475            double hieman = height * 0.75;
476            flame.Position = crawly.Position + new Vector(0, hieman);
477        };
478        flameMover.Start();
479
480        PlatformWandererBrain brain = new PlatformWandererBrain();
481        brain.Speed = 20;
482        brain.FallsOffPlatforms = true;
483
484        crawly.Brain = brain;
485
486        // Sammuu törmätessään maitoon.
487        AddCollisionHandler(crawly, "milkparticle", delegate(PhysicsObject c, PhysicsObject particle)
488        {
489            particle.Destroy();
490            crawly.Brain = null;
491            crawly.Animation = new Animation(crawly.Animation.CurrentFrame);
492            crawly.Tag = "";
493            flame.Destroy();
494            RemoveCollisionHandlers(crawly);
495        });
496    }
497
498    void CreateFireMage(Vector position, double width, double height)
499    {
500        PlatformCharacter mage = new PlatformCharacter(width * 3, height * 4);
501        mage.Position = position;
502        mage.Y += mage.Height / 2.0;
503        mage.Tag = "burn";
504        mage.Tag += "fireMage";
505        mage.AnimWalk = new Animation(firemageAnimation);
506        mage.CollisionIgnoreGroup = 3;
507        Add(mage, 1);
508        bool immune = false;
509
510        // Pään päällä oleva liekki (taitaa olla vähän huonossa kohtaa tällä hetkellä)
511        PhysicsObject flame = new PhysicsObject(width * 1.4, height * 2);
512        flame.Y += mage.Height * 0.65;
513        //flame.Y = mage.Y +  mage.Height;
514        flame.Animation = new Animation(blaze);
515        flame.IgnoresPhysicsLogics = true;
516        flame.Animation.Start();
517        mage.Add(flame);
518
519        PlatformWandererBrain brain = new PlatformWandererBrain();
520        brain.Speed = 20;
521        brain.FallsOffPlatforms = false;
522        mage.Brain = brain;
523
524        PhysicsObject trigger = PhysicsObject.CreateStaticObject(10, Level.Height); //A truly cool and efficient way to make the boogeyman react only to our closeness
525        trigger.Position = mage.Position - new Vector(Window.Width / 2, 0);
526        //trigger.Color = Color.Red;
527        trigger.IsVisible = false;
528        trigger.IgnoresCollisionResponse = true;
529        Add(trigger);
530
531        // Taiotaan tulta välillä.
532        var castTimer = new Timer { Interval = 10.0 };
533        castTimer.Timeout += delegate
534        {
535            // TODO: Kävelyanimaatio pysähtyy jostain syystä tämän animaation jälkeen.
536            mage.PlayAnimation(firemageCastAnimation);
537
538            Timer.SingleShot(1.5, 
539                delegate 
540                {
541                    for (int i = 0; i < 6; i++)
542                    {
543                        CreateFlame(new Vector(mage.X + RandomGen.NextDouble(-300, 300), mage.Y + mage.Height * 1.5), 30, 60, false);
544
545                        //PhysicsObject fire = new PhysicsObject(30, 60);
546                        //fire.CanRotate = false;
547                        //fire.Tag = "burn";
548                        //fire.Animation = new Animation(blaze) { FPS = RandomGen.NextInt(20, 26) };
549                        //fire.Animation.Step(RandomGen.NextInt(0, 12));
550                        //fire.Animation.Resume();
551                        //fire.X = mage.X + RandomGen.NextDouble(-300, 300);
552                        //fire.Y = mage.Y + mage.Height * 1.5;
553                        //fire.CollisionIgnoreGroup = 3;
554                        //Add(fire);
555
556                        //AddCollisionHandler(fire, "milkparticle", delegate(PhysicsObject c, PhysicsObject particle)
557                        //{
558                        //    particle.Destroy();
559                        //    fire.Destroy();
560                        //});
561                    }
562                });
563           
564        };
565        //castTimer.Start();
566
567        AddCollisionHandler(mage, "milkparticle", delegate(PhysicsObject fireMage, PhysicsObject milk)
568        {
569            if (milk.Y > fireMage.Y + fireMage.Height * 0.15 && !immune)
570            {
571                flame.Size *= 0.9;
572                immune = true;
573                if (flame.Height < height)
574                {
575                    mage.Destroy();
576                    castTimer.Stop();
577                    //NextLevel();
578                }
579                Timer.SingleShot(0.5, delegate { immune = false; });
580
581            }
582        });
583
584        AddCollisionHandler(trigger, "player", delegate(PhysicsObject a, PhysicsObject b){ castTimer.Start(); });
585    }
586
587    void CreateHouse(Vector position, double width, double height)
588    {
589        // Näkyvä talo
590        GameObject house = new GameObject(width * 10, height * 8);
591        house.Image = houseImages[0];
592        house.Position = position - new Vector(0, height * 2.5);
593        Add(house, -2);
594
595        //Seisottava tasanne
596        PhysicsObject platform = PhysicsObject.CreateStaticObject(house.Width - (TILE_SIZE * 3.25), 1);     //Tätä kohtaa on nyt vähän hakemalla haettu.
597        platform.IsVisible = false;
598        platform.Position = new Vector(house.X + (TILE_SIZE * 0.5), house.Top);
599        Add(platform);
600    }
601
602    void CreateBurnedHouse(Vector position, double width, double height)
603    {
604        GameObject house = new GameObject(width * 10, height * 8);
605        house.Image = houseImages[1];
606        house.Position = position - new Vector(0, height * 2.5);
607        Add(house, -2);
608
609        PhysicsObject platform = PhysicsObject.CreateStaticObject(house.Width * 0.25, 1);
610        platform.IsVisible = false;
611        platform.Position = new Vector(house.X + platform.Width * 0.5, house.Top);
612        Add(platform);
613    }
614
615    private void CreateCart(Vector position, double width, double height)
616    {
617        double size = 0.7;
618        PhysicsObject cart = new PhysicsObject(400 * size, 80 * size);
619        cart.Position = position;
620        cart.Image = cartImage;
621        cart.CollisionIgnoreGroup = 2;
622        Add(cart);
623        PhysicsObject cartWheel = new PhysicsObject(160 * size, 160 * size, Shape.Circle);
624        cartWheel.Image = cartWheelImage;
625        cartWheel.Position = cart.Position + new Vector(-110, -30) * size;
626        cartWheel.CollisionIgnoreGroup = 2;
627        Add(cartWheel);
628        AxleJoint joint = new AxleJoint(cart, cartWheel);
629        Add(joint);
630    }
631
632    private void CreateDummy(Vector position, double width, double height, Color color)
633    {
634        PhysicsObject dummy = PhysicsObject.CreateStaticObject(width, height);
635        dummy.Position = position;
636        dummy.Color = color;
637        Add(dummy);
638    }
639
640    void CreatePlayer(Vector position, double width, double height)
641    {
642        HillBilly player = new HillBilly(width, height * 2);
643        player.Shape = Shape.Rectangle;
644        player.Position = position + new Vector(0, height * 0.5);
645        player.Color = Color.White;
646        player.AnimWalk = new Animation(normalWalk);
647        player.AnimIdle = new Animation(playerIdle);
648        player.AnimJump = new Animation(playerJump);
649        player.AnimFall = new Animation(playerFall);
650        player.AnimFall.StopOnLastFrame = true;
651        players.Add(player);
652        startingPlayers.Add(player);
653        player.Tag = "player";
654        Add(player);
655        AddCollisionHandler(player, "burn", delegate(PhysicsObject p, PhysicsObject t)
656        {
657            HillBilly billy = p as HillBilly;
658            billy.Life.Value--;
659
660        });
661
662        player.Life.LowerLimit += delegate
663        {
664            if (players.Count < 2)
665            {
666                Loss();
667            }
668            else { players.Remove(player); player.Destroy(); }
669        };
670
671        AddCollisionHandler(player, "milk", CollectMilk);
672    }
673
674    void CreateGroundTop(Vector position, double width, double height)
675    {
676        // Puolet pienempi näkymätön palikka alla johon törmää.
677        PhysicsObject ground = PhysicsObject.CreateStaticObject(width, height / 2.0);
678        ground.IsVisible = false;
679        ground.Position = position - new Vector(0.0, TILE_SIZE / 4.0);
680        Add(ground);
681
682        // Maanpinnan näkyvä osa.
683        GameObject visibleGround = new GameObject(width, height);
684        visibleGround.Image = groundImages[levelNumber];
685        visibleGround.Position = position;
686        visibleGround.TextureWrapSize = new Vector(width / TILE_SIZE, height / TILE_SIZE);
687        Add(visibleGround, -1);
688
689        int probability = RandomGen.NextInt(100);
690        bool wheat = probability < 20;
691
692        if (wheat)
693        {
694            GameObject wheatBlock = new GameObject(width * 1.5, height * 2);
695            wheatBlock.Image = foregroundDecorations[0];
696            wheatBlock.X = visibleGround.X;
697            wheatBlock.Bottom = visibleGround.Bottom;
698            wheatBlock.TextureWrapSize = new Vector(width / TILE_SIZE, height / TILE_SIZE);
699            Add(wheatBlock, 2);
700        }
701    }
702
703    void CreateGround(Vector position, double width, double height)
704    {
705        PhysicsObject ground = PhysicsObject.CreateStaticObject(width, height);
706        ground.Image = groundTopImages[levelNumber];
707        ground.Position = position;
708        ground.TextureWrapSize = new Vector(width / TILE_SIZE, height / TILE_SIZE);
709        Add(ground);
710    }
711    #endregion
712
713    void SetControls()
714    {
715        Keyboard.Listen(Key.A, ButtonState.Down, delegate { startingPlayers[0].Walk(-PLAYER_SPEED); }, "Player 1 moves left");
716        Keyboard.Listen(Key.D, ButtonState.Down, delegate { startingPlayers[0].Walk(PLAYER_SPEED); }, "Player 1 moves right");
717        Keyboard.Listen(Key.W, ButtonState.Down, delegate { startingPlayers[0].Jump(PLAYER_SPEED * 2); }, "Player 1 jumps");    //Just PLAYER_SPEED felt alright as well
718        Keyboard.Listen(Key.E, ButtonState.Pressed, UseImprovement, "Player 1 uses their tools", startingPlayers[0]);
719
720        Keyboard.Listen(Key.Left, ButtonState.Down, delegate { startingPlayers[1].Walk(-PLAYER_SPEED); }, "Player 2 moves left");
721        Keyboard.Listen(Key.Right, ButtonState.Down, delegate { startingPlayers[1].Walk(PLAYER_SPEED); }, "Player 2 moves right");
722        Keyboard.Listen(Key.Up, ButtonState.Down, delegate { startingPlayers[1].Jump(PLAYER_SPEED * 2); }, "Player 2 jumps");
723        Keyboard.Listen(Key.RightShift, ButtonState.Pressed, UseImprovement, "Player 2 uses their tools", startingPlayers[1]);
724
725        Keyboard.Listen(Key.F12, ButtonState.Pressed, NextLevel, null);
726
727        Keyboard.Listen(Key.F1, ButtonState.Pressed, ShowControlHelp, "Show help");
728        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, "Exit game");
729    }
730
731    public void CreateMilkParticles(HillBilly billy)
732    {
733        for (int i = 0; i < 10; i++)
734        {
735            const double maxLife = 1.0;
736            PhysicsObject milkParticle = new PhysicsObject(10, 10, Shape.Circle);
737            milkParticle.Color = new Color(255, 255, 255, 128);
738            milkParticle.Position = billy.Position + new Vector(0, -30);
739            milkParticle.IgnoresCollisionResponse = true;
740            milkParticle.Tag = "milkparticle";
741            milkParticle.LifetimeLeft = TimeSpan.FromSeconds(maxLife);
742            Add(milkParticle);
743
744            // Väri muuttuu läpinäkyväksi.
745            var fadeTimer = new Timer { Interval = 0.07 };
746            fadeTimer.Timeout += delegate
747            {
748                byte c = 255;
749                milkParticle.Color = new Color(c, c, c, (byte)(128 * milkParticle.LifetimeLeft.TotalSeconds / maxLife));
750            };
751            fadeTimer.Start();
752            milkParticle.Destroyed += fadeTimer.Stop;
753
754            // Random lentonopeus.
755            var rx = RandomGen.NextDouble(-50, 50);
756            var ry = RandomGen.NextDouble(-50, 50);
757            milkParticle.Hit(new Vector(billy.FacingDirection.GetVector().X * (200 + rx), 300 + ry));
758        }
759    }
760
761    private void UseImprovement(HillBilly player)
762    {
763        if (player.Improvement == null)
764        {
765            player.Jump(200);   //TODO: CRY ALL THE TEARS  :'(
766            return;
767        }
768
769        player.UseImprovement(player.Improvement);
770    }
771
772    void Loss()
773    {
774        //TODO: Sumthin' flashy for our fallen friends.
775        Exit();
776    }
777
778    void CollectMilk(PhysicsObject player, PhysicsObject milk)
779    {
780        HillBilly billy = player as HillBilly;
781        if (billy == null)
782            return;
783
784        Improvement milkI = milk as Improvement;
785        billy.GainImprovement(milkI);
786
787        milk.Destroy();
788        //billy.AnimWalk = new Animation(milkWalk);
789        //billy.AnimIdle = new Animation(milkWalk.CurrentFrame);
790    }
791
792    #region Camera
793    void UpdateCamera()
794    {
795        double minY = players.Min(p => p.Y);
796        double maxY = players.Max(p => p.Y);
797        double minX = players.Min(p => p.X) + cameraOffset;
798
799        Vector minPosition = new Vector(Math.Max(minX, cameraTargetX), minY);
800        Vector maxPosition = new Vector(minX, maxY);
801
802        cameraTarget = (minPosition + maxPosition) * 0.5;
803        cameraTarget.X = Math.Max(cameraTargetX, minX);     //Lellllll.
804
805        //cameraTarget.Y = Math.Max(cameraTarget.X, Level.Bottom + Window.Height/2.0);
806
807        cameraTargetX = Math.Max(cameraTargetX, minX);
808
809        cameraTarget.X = Math.Min(cameraTargetX, rightCamLimit);
810        cameraTarget.Y = Math.Max(cameraTarget.Y, bottomCamLimit);
811
812        double windowMax = Camera.ScreenToWorld(new Vector(Window.Width / 2.0, 0)).X;
813        double windowMin = Camera.ScreenToWorld(new Vector(-Window.Width / 2.0, 0)).X;
814        foreach (var player in players)
815        {
816            player.Left = Math.Max(player.Left, windowMin);
817            player.Right = Math.Min(player.Right, windowMax);
818        }
819    }
820
821    protected override void Update(Time time)
822    {
823        Camera.Position += (cameraTarget - Camera.Position) * time.SinceLastUpdate.TotalSeconds * cameraSpeed;
824        //Camera.X += (cameraTargetX - Camera.X) * time.SinceLastUpdate.TotalSeconds * cameraSpeed;
825
826
827        base.Update(time);
828    }
829
830    /// <summary>
831    /// Yritän leikkiä kameralla. Vielä varmaan hetken pidempään.
832    /// </summary>
833    /// <param name="gameTime"></param>
834    /*
835    protected override void Update(Microsoft.Xna.Framework.GameTime gameTime)
836    {
837        foreach(HillBilly player in players)
838        {
839            playerPositionsX.Add(player.Position.X);
840            playerPositionsY.Add(player.Position.Y);
841        }
842
843        double maxX = playerPositionsX.Max();
844        double maxY = playerPositionsY.Max();
845        double minX = playerPositionsX.Min();
846        double minY = playerPositionsY.Min();
847
848        Vector minPosition = new Vector(minX, minY);
849        Vector maxPosition = new Vector(maxX, maxY);
850
851        Camera.Position = (minPosition + maxPosition) * 0.5;
852
853        playerPositionsX.Clear();
854        playerPositionsY.Clear();
855
856        base.Update(gameTime);
857    }
858     */
859    #endregion
860}
Note: See TracBrowser for help on using the repository browser.