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

Revision 6310, 35.5 KB checked in by empaheik, 8 years ago (diff)

Heinähanko + parannusten uudelleenpoimiminen + paranneltu Improvement-luokka tovereineen.

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