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

Revision 6301, 34.7 KB checked in by sieerinn, 5 years ago (diff)

Tulipalleron animaatio.

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