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

Revision 6295, 32.3 KB checked in by empaheik, 5 years ago (diff)

Nimet + elämät, etualan ruohot (optimointia vähentämällä, hmm), kenttä vaihtuu, kun bossin tappaa, restart.

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