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

Revision 6307, 33.4 KB checked in by empaheik, 5 years ago (diff)

Noita vaihtelee eri aivojen välillä, tähtää tulimyrskyn pelaajaan.

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