source: 2010/23/hniemi/oksa/ShootEmUp/ShootEmUp/Peli.cs @ 1007

Revision 1007, 21.0 KB checked in by hniemi, 10 years ago (diff)
Line 
1using System;
2using Jypeli;
3using Jypeli.ScreenObjects;
4using Jypeli.Assets;
5using System.Collections.Generic;
6
7
8namespace ShootEmUp
9{
10    public class Peli : PhysicsGame
11    {
12        #region Julistukset
13       
14       
15        //Liikkumisnopeudet
16        private const double NOPEUS = 300;
17        private const int OLETUSASE = 0;
18        private Vector nopeusPysty = new Vector(0,NOPEUS);
19        private Vector nopeusVaaka = new Vector(NOPEUS, 0);
20
21        //Kentän rakenne
22        private Alus pelaajaAlus;
23        private PhysicsObject vasenLaita;
24        private PhysicsObject oikeaLaita;
25        private PhysicsObject pohja;
26        private PhysicsObject katto;
27        private PhysicsObject exitZone;
28
29        private GameObject[] tahdet;
30
31        //Viholliset
32        private const int VIHOLLISKUVIA = 4;
33
34        //Statistiikka
35        private int kentannro = 0;
36        private IntMeter score = new IntMeter(0);
37        private IntMeter lives = new IntMeter(3);
38        private TextDisplay[] aseNimet;
39        private Weapon[] weapons;
40
41        private bool bossmode = true;
42
43        #endregion
44
45        /// <summary>
46        /// Aloittaa pelin
47        /// </summary>
48        protected override void Begin()
49        {
50            LataaKentta(kentannro);
51        }
52
53        /// <summary>
54        /// Päivityssilmukka, hoitaa tällä hetkellä manuaalisesti vain
55        /// taustan liikuttamisen
56        /// </summary>
57        /// <param name="time"></param>
58        protected override void Update(Time time)
59        {
60            if (tahdet != null)
61            {
62                for (int i = 0; i < tahdet.Length; i++)
63                {
64                    tahdet[i].Y -= 30;
65                    if (tahdet[i].Y < Level.Bottom - 40) tahdet[i].Y = Level.Top + 100;
66                }
67            }
68
69            base.Update(time);
70        }
71
72        #region Kentän lataaminen
73
74        /// <summary>
75        /// Tulee lataamaan numeroa vastaavan kentän
76        /// Kentän tiedot siis tallennettaisiin level1.txt, level2.txt...
77        /// </summary>
78        /// <param name="kentanNumero">Ei vielä käytössä</param>
79        void LataaKentta(int kentanNumero)
80        {
81            ClearAll();
82            Level.Width = 600;
83            Level.Height = 800;
84
85            Camera.Move(new Vector(250, 0));
86            //Camera.Zoom(0.2);
87           
88            //Laidat
89            LisaData tieto = new LisaData();
90            tieto.Tyyppi = "seina";
91            tieto.Rajahtaa = true;
92            tieto.Damage = 5;
93
94            PhysicsObject[] kulmat = new PhysicsObject[4];
95
96            for (int i = 0; i < kulmat.Length; i++)
97            {
98                kulmat[i] = PhysicsObject.CreateStaticObject(60, 60);
99                kulmat[i].Image = LoadImage("seina/seinaKulma");
100                kulmat[i].Tag = tieto;
101                kulmat[i].Angle = Angle.Degrees(i * 90);
102                Add(kulmat[i]);
103            }
104            kulmat[3].Position = new Vector(Level.Left - 30, Level.Top+30);
105            kulmat[2].Position = new Vector(Level.Right + 30, Level.Top + 30);
106            kulmat[0].Position = new Vector(Level.Left - 30, Level.Bottom - 30);
107            kulmat[1].Position = new Vector(Level.Right + 30, Level.Bottom - 30);
108
109
110            //Seinät
111            Level.BackgroundColor = Color.Black;
112
113            vasenLaita = Level.CreateLeftBorder();
114            vasenLaita.Image = LoadImage("seina/seinaOikea");
115            vasenLaita.Angle = Angle.Degrees(270);
116            vasenLaita.Tag = tieto;
117
118            oikeaLaita = Level.CreateRightBorder();
119            oikeaLaita.Image = LoadImage("seina/seinaOikea");
120            oikeaLaita.Angle = Angle.Degrees(90);
121            oikeaLaita.Tag = tieto;
122
123            pohja = Level.CreateBottomBorder();
124            pohja.Image = LoadImage("seina/seinaOikea");
125            pohja.Angle = Angle.Degrees(0);
126            pohja.Size = new Vector(pohja.Width - 120, pohja.Height);
127            pohja.Tag = tieto;
128
129            katto = Level.CreateTopBorder();
130            katto.Image = LoadImage("seina/seinaOikea");
131            katto.Angle = Angle.Degrees(180);
132            katto.Size = new Vector(katto.Width - 120, katto.Height);
133            katto.Tag = tieto;
134
135            //Exit-alueen tekeminen.
136            exitZone = PhysicsObject.CreateStaticObject(Level.Width, 200);
137            exitZone.Position = new Vector(Level.Center.X, Level.Bottom - exitZone.Size.Y / 2 - 5);
138            exitZone.Tag = tieto;
139            exitZone.IsVisible = false;
140            Add(exitZone);
141
142           
143            LuoPelaaja();
144            LataaHUD();
145            LataaKontrollit(pelaajaAlus);
146            LataaTausta(kentanNumero);
147            LataaViholliset(20, 4,10);
148           
149        }
150
151        /// <summary>
152        /// Luo näytölle tarvittavat mittarit
153        /// </summary>
154        void LataaHUD()
155        {
156            ValueDisplay[] naytot = new ValueDisplay[3];
157            for (int i = 0; i < naytot.Length; i++)
158            {
159                naytot[i] = new ValueDisplay();
160                Add(naytot[i]);
161                naytot[i].TextColor = Color.White;
162                naytot[i].ValueColor = Color.Yellow;
163                naytot[i].Position = new Vector(Level.Right + 40, Level.Top - 80 - (30*i));
164            }
165
166            naytot[0].BindTo(pelaajaAlus.HpMeter);
167            naytot[1].BindTo(score);
168            naytot[2].BindTo(lives);
169            naytot[0].Text = "HP: ";
170            naytot[1].Text = "SCORE: ";
171            naytot[2].Text = "LIVES: ";
172
173            aseNimet = new TextDisplay[3];
174            for (int i = 0; i < aseNimet.Length; i++)
175            {
176                aseNimet[i] = new TextDisplay();
177                aseNimet[i].TextColor = Color.White;
178                aseNimet[i].Position = new Vector(Level.Right + 40, Level.Top - 200 - (30 * i));
179                Add(aseNimet[i]);
180            }
181            aseNimet[OLETUSASE].TextColor = Color.Yellow;
182            aseNimet[0].Text = "Beam";
183            aseNimet[1].Text = "Missile";
184            aseNimet[2].Text = "Photon";
185
186            Timer purkkaAjastin = new Timer();
187            purkkaAjastin.Interval = 0.01;
188            purkkaAjastin.Trigger += Purkkakorjaus;
189            Add(purkkaAjastin);
190            purkkaAjastin.Start(1);
191           
192        }
193
194        void Purkkakorjaus(Timer sender)
195        {
196            VaihdaAsetta(1);
197        }
198
199        /// <summary>
200        /// Lataa taustalle tähdet
201        /// </summary>
202        /// <param name="kentanNumero"></param>
203        void LataaTausta(int kentanNumero)
204        {
205            tahdet = new GameObject[15];
206            for (int i = 0; i < tahdet.Length; i++)
207            {
208                GameObject tahti = new GameObject(3, 3);
209                tahti.Color = Color.White;
210                tahti.Position = new Vector(RandomGen.NextDouble(Level.Left, Level.Right),
211                                            RandomGen.NextDouble(Level.Top +20, Level.Top + 2000));
212                tahdet[i] = tahti;
213
214                Add(tahti);
215            }
216        }
217
218        /// <summary>
219        /// Luo pelaajan ja sijoittaa sen kentälle.
220        /// Asettaa pelaajalle myös aseen.
221        /// </summary>
222        void LuoPelaaja()
223        {
224            pelaajaAlus = new Alus(60, 55, 10);
225            pelaajaAlus.Shape = Shapes.Triangle;
226           
227            pelaajaAlus.Animation = new Animation(LoadImages("sankarialus/sankarialusThrust1", "sankarialus/sankarialusThrust2"));
228            pelaajaAlus.Animation.Start();
229
230            LisaData tieto = new LisaData();
231            tieto.Tyyppi = "oma";
232            tieto.Rajahtaa = true;
233            tieto.Damage = 5;
234            pelaajaAlus.Tag = tieto;
235
236            pelaajaAlus.Angle += Angle.Degrees(90);
237
238            pelaajaAlus.IgnoresCollisionResponse = false;
239            pelaajaAlus.Y = Level.Bottom + 40;
240            pelaajaAlus.KineticFriction = 1.0;
241            pelaajaAlus.Mass = 100000;
242
243            weapons = new Weapon[3];
244
245            //LoadImage("sade");
246
247            weapons[0] = new Beam(5, 35, LoadImage("sade"));
248            ((ShmupWeapon)weapons[0]).ProjectileCollision = AmmusOsuu;
249            weapons[0].Position = new Vector(0, -40);
250            weapons[1] = new Missile(15, 30, LoadImage("ohjus"));
251            ((ShmupWeapon)weapons[1]).ProjectileCollision = AmmusOsuu;
252
253            weapons[2] = new Photon(15, 15, LoadImage("photon"));
254            ((ShmupWeapon)weapons[2]).ProjectileCollision = AmmusOsuu;
255
256            for (int i = 0; i < weapons.Length; i++)
257            {
258                weapons[i].IsVisible = false;
259                pelaajaAlus.Add(weapons[i]);
260            }
261
262            Add(pelaajaAlus);
263           
264           
265            AddCollisionHandler(pelaajaAlus, PelaajaTormaa);
266        }
267
268        #endregion
269        #region Kontrollit ja liikkuminen
270        /// <summary>
271        /// Asettaa kontrollit ohjaamaan haluttua alusta
272        /// </summary>
273        /// <param name="pelaaja">Alus, jota halutaan ohjata</param>
274        void LataaKontrollit(Alus pelaaja)
275        {
276            Keyboard.Listen(Key.Escape, ButtonState.Pressed, Exit, "Lopettaa pelin");
277            Keyboard.Listen(Key.Up, ButtonState.Down, Liikuta, "Liikuttaa alusta ylös", pelaaja, nopeusPysty);
278            Keyboard.Listen(Key.Up, ButtonState.Released, pelaaja.StopVertical, null);
279            Keyboard.Listen(Key.Down, ButtonState.Down, Liikuta, "Liikuttaa alusta alas", pelaaja, -nopeusPysty);
280            Keyboard.Listen(Key.Down, ButtonState.Released, pelaaja.StopVertical, null);
281            Keyboard.Listen(Key.Left, ButtonState.Down, Liikuta, "Liikuttaa alusta vasemmalle", pelaaja, -nopeusVaaka);
282            Keyboard.Listen(Key.Left, ButtonState.Released, pelaaja.StopHorizontal, null);
283            Keyboard.Listen(Key.Right, ButtonState.Down, Liikuta, "Liikuttaa alusta oikealle", pelaaja, nopeusVaaka);
284            Keyboard.Listen(Key.Right, ButtonState.Released, pelaaja.StopHorizontal, null);
285            Keyboard.Listen(Key.LeftControl, ButtonState.Down, Ammu, "Lopettaa pelin", pelaajaAlus);
286            Keyboard.Listen(Key.D1, ButtonState.Pressed, VaihdaAsetta, "Valitsee säde-aseen", 1);
287            Keyboard.Listen(Key.D2, ButtonState.Pressed, VaihdaAsetta, "Valitsee ohjuksen", 2);
288            Keyboard.Listen(Key.D3, ButtonState.Pressed, VaihdaAsetta, "Valitsee fotoniaseen", 3);
289        }
290
291        /// <summary>
292        /// Liikuttaa alusta haluttuun suuntaan
293        /// </summary>
294        /// <param name="alus">Liikutettava alus</param>
295        /// <param name="suunta">Liikutettava suunta</param>
296        void Liikuta(Alus alus, Vector suunta)
297        {
298            if (-NOPEUS < alus.Velocity.Y && alus.Velocity.Y < NOPEUS && suunta.Y != 0)
299            {
300                alus.Velocity += suunta;
301            }
302            if (-NOPEUS < alus.Velocity.X && alus.Velocity.X < NOPEUS && suunta.X != 0)
303            {
304                alus.Velocity += suunta;
305            }
306        }
307
308        void VaihdaAsetta(int aseenNumero)
309        {
310            if (aseenNumero > 0 && aseenNumero < 4)
311            {
312                pelaajaAlus.SetWeapon(weapons[aseenNumero-1]);
313                for (int i = 0; i < aseNimet.Length; i++)
314                {
315                    aseNimet[i].TextColor = Color.White;
316                }
317                aseNimet[aseenNumero-1].TextColor = Color.Yellow;
318            }
319        }
320
321        /// <summary>
322        /// Ampuu aluksella
323        /// </summary>
324        /// <param name="alus">Alus joka ampuu</param>
325        void Ammu(Alus alus)
326        {
327            Add(alus.Shoot());
328        }
329
330        #endregion
331        #region Viholliset
332        /// <summary>
333        /// Lataa viholliset
334        /// TODO: Kentän numeron huomioiminen
335        ///
336        /// Jos bossmode on päällä, lähettää vain loppupomon.
337        /// </summary>
338        void LataaViholliset(int maara, double min, double max)
339        {
340            List<AikaTapahtuma> vihollistenTuloajat = new List<AikaTapahtuma>();
341
342            if (!bossmode)
343            {
344                for (int i = 0; i < maara; i++)
345                {
346                    vihollistenTuloajat.Add(new AikaTapahtuma(2 + (i * 5), LahetaSatunnainenVihollislaivue, 4, 10));
347                }
348                vihollistenTuloajat.Add(new AikaTapahtuma(2 + (maara * 5), LahetaLoppupomo, 1, 20));
349            }
350            else
351            {
352                vihollistenTuloajat.Add(new AikaTapahtuma(0, LahetaLoppupomo, 1, 20));
353            }
354            foreach (AikaTapahtuma tapahtuma in vihollistenTuloajat)
355            {
356                Timer ajastin = new Timer();
357                ajastin.Tag = tapahtuma.Lahtopaikka;
358                ajastin.Interval = tapahtuma.Aika;
359                ajastin.Trigger += tapahtuma.Tapahtuma;
360                Add(ajastin);
361                ajastin.Start(1);
362            }
363        }
364
365        /// <summary>
366        /// Luo alukset ja lähettää ne matkaan
367        /// </summary>
368        /// <param name="sender">Timerin tagissa on lähtökoordinaatti</param>
369        /// <param name="lahetysX">X-koordinaatti, josta muodostelma lähtee</param>
370        void LahetaLoppupomo(Timer sender)
371        {
372            double taso = ((Vector)sender.Tag).X;
373
374            List<Alus> alukset = new List<Alus>();
375            Image vihollisenKuva = LoadImage("loppuvastus" + 1);
376            alukset.Add(LuoVihollinen(vihollisenKuva, 400));
377            alukset[0].Position = new Vector(0, Level.Top + 200);
378            alukset[0].Angle = Angle.Degrees(270);
379            Add(alukset[0]);
380
381            //ase.ProjectileCollision = AmmusOsuu;
382
383            Timer Purkkakorjaus = new Timer();
384            Purkkakorjaus.Tag = alukset[0];
385            Purkkakorjaus.Interval = 0.1;
386            Purkkakorjaus.Trigger += Purkkakorjaus2;
387            Add(Purkkakorjaus);
388            Purkkakorjaus.Start();
389
390            //Lisää ampuma-ajastimen
391            Timer ampumaAjastin = new Timer();
392            ampumaAjastin.Interval = 0.7;
393            ampumaAjastin.Trigger += alukset[0].Shoot;
394            Add(ampumaAjastin);
395            ampumaAjastin.Start();
396
397            List<Vector> reitti = new List<Vector>();
398            reitti.Add(new Vector(-200, Level.Top - 100 ));
399            reitti.Add(new Vector(200, Level.Top - 100));
400
401            Muodostelma muodostelma = new Muodostelma(alukset, reitti, LuoLahettaja());
402            muodostelma.MovingSpeed = 100;
403            muodostelma.Start();
404        }
405
406        void Purkkakorjaus2(Timer sender)
407        {             
408            //Aseen säätö
409           
410            Photon ase = new Photon(10, 10, LoadImage("photon"));
411            Add(ase);
412            ase.Data.Damage = 20;
413            ase.Data.Rajahtaa = false;
414            ase.Data.Tyyppi = "vihollinen";
415            ((Alus)sender.Tag).Add(ase);
416            ((Alus)sender.Tag).SetWeapon(ase);
417        }
418
419        /// <summary>
420        /// Arpoo ja lähettää satunnaisen vihollislaivueen
421        /// Laivueessa on tällä hetkellä 10 alusta
422        /// Aluksen kuva arvotaan tiedostoista, joiden nimi on "vihollinen#.png"
423        /// </summary>
424        /// <param name="sender"></param>
425        void LahetaSatunnainenVihollislaivue(Timer sender)
426        {
427            List<Alus> alukset = new List<Alus>();
428            Image vihollisenKuva = LoadImage("vihollinen" + RandomGen.NextInt(1,VIHOLLISKUVIA));
429
430            int min = (int)((Vector)sender.Tag).X;
431            int max = (int)((Vector)sender.Tag).Y;
432            int koko = RandomGen.NextInt(min, max);
433
434            for (int i = 0; i < koko; i++)
435            {
436                alukset.Add(LuoVihollinen(vihollisenKuva, 40));
437                Add(alukset[i]);
438                Angle alas = new Angle();
439                alas.Degree = 270;
440                alukset[i].Angle = Angle.Degrees(270);
441                alukset[i].Position = new Vector(0, Level.Top + 200);
442                AddCollisionHandler(alukset[i], VihollinenTormaa);
443            }
444
445            IList<Vector> reitti = ArvoReitti(RandomGen.NextInt(0,5));
446            Muodostelma muodostelma = new Muodostelma(alukset, reitti, LuoLahettaja());
447            muodostelma.MovingSpeed = 200;
448            muodostelma.Start();
449        }
450
451        /// <summary>
452        /// Arpoo koneelle reitin, joka lähteee ylhäältä ja päätyy alas
453        /// </summary>
454        /// <param name="valipisteet">Välipisteiden määrä, 0 -></param>
455        /// <returns></returns>
456        List<Vector> ArvoReitti(int valipisteet)
457        {
458            List<Vector> reitti = new List<Vector>();
459            reitti.Add(new Vector(RandomGen.NextDouble(Level.Left + 30, Level.Right - 30),Level.Top + 80));
460            for (int i = 0; i < valipisteet; i++)
461            {
462                reitti.Add(new Vector(RandomGen.NextDouble(Level.Left + 30, Level.Right - 30),
463                                     (RandomGen.NextDouble(Level.Bottom + 30, Level.Top - 100))));
464            }
465            reitti.Add(new Vector(RandomGen.NextDouble(Level.Left + 30, Level.Right - 30), Level.Bottom - 35));
466            return reitti;
467        }
468
469        Alus LuoVihollinen(Image kuva, int hp)
470        {
471           
472            Alus vihollinen = new Alus(kuva.Width/5, kuva.Height/5, hp);
473            vihollinen.Image = kuva;
474            LisaData tieto = new LisaData();
475            tieto.Tyyppi = "vihollinen";
476            tieto.Rajahtaa = true;
477            tieto.Damage = 5;
478            vihollinen.Tag = tieto;
479            return vihollinen;
480        }
481
482        /// <summary>
483        /// Luo ajastimen
484        /// Lisää myös ajastimen, joten voidaan kutsua suoraan Muodostelman muodostajassa.
485        /// </summary>
486        /// <returns></returns>
487        Timer LuoLahettaja()
488        {
489            Timer ajastin = new Timer();
490            ajastin.Interval = 0.5;
491            Add(ajastin);
492            return ajastin;
493        }
494        #endregion
495        #region Tapahtumat
496        /// <summary>
497        /// Pelaajan törmäyksen käsittelijä
498        ///
499        /// Katsoo myös, että pelaaja ei juutu seiniin
500        /// </summary>
501        /// <param name="tormaaja"></param>
502        /// <param name="kohde"></param>
503        void PelaajaTormaa(PhysicsObject tormaaja, PhysicsObject kohde)
504        {
505            if (((LisaData)kohde.Tag).Tyyppi == "vihollinen") 
506            {
507                ((Alus)tormaaja).TakeHit(5);
508                if (kohde is Alus) ((Alus)kohde).TakeHit(20);
509            }
510
511            if (kohde == vasenLaita)
512            {
513                tormaaja.X = Level.Left + tormaaja.Height / 2 + 1;
514                tormaaja.StopHorizontal();
515            }
516
517            if (kohde == oikeaLaita)
518            {
519                tormaaja.X = Level.Right - tormaaja.Height / 2 - 1;
520                tormaaja.StopHorizontal();
521            }
522            if (kohde == katto)
523            {
524                tormaaja.Y = Level.Top - tormaaja.Width / 2 - 1;
525                tormaaja.StopVertical();
526            }
527            if (kohde == pohja)
528            {
529                tormaaja.Y = Level.Bottom + tormaaja.Width/2 +1;
530                tormaaja.StopVertical();
531            }
532
533        }
534
535        /// <summary>
536        /// Mitä tapahtuu, kun vihollinen tulee ns. poistumisalueelle
537        /// </summary>
538        /// <param name="tormaaja"></param>
539        /// <param name="kohde"></param>
540        void VihollinenTormaa(PhysicsObject tormaaja, PhysicsObject kohde)
541        {
542            if (kohde == exitZone) Remove(tormaaja);
543           
544        }
545
546        void AmmusOsuu(PhysicsObject ammus, PhysicsObject toinen)
547        {
548
549            if (toinen.Tag.ToString() == "seina" || ((LisaData)toinen.Tag).Tyyppi != ((LisaData)ammus.Tag).Tyyppi)
550            {
551                ammus.Destroy();
552                if (((LisaData)ammus.Tag).Rajahtaa)
553                {
554                    Explosion rajahdys = new Explosion(100);
555                    rajahdys.Position = toinen.Position;
556                    Add(rajahdys);
557                }
558
559                if (((LisaData)toinen.Tag).Tyyppi == "vihollinen")
560                {
561                    if (toinen is Alus) 
562                    {
563                        ((Alus)toinen).TakeHit(((LisaData)ammus.Tag).Damage);
564                        if (toinen.IsDestroyed()) score.Value += 300;
565                    }
566                   
567                }
568            }
569
570
571        }
572        #endregion
573    }
574
575    public class AikaTapahtuma 
576    {
577        public int Aika;
578        public Timer.TriggerHandler Tapahtuma;
579        private Vector lahtopaikka;
580
581        public Vector Lahtopaikka
582        {
583            get{ return lahtopaikka; }
584        }
585
586        public AikaTapahtuma(int aika, Timer.TriggerHandler tapahtuma, double param1, double param2)
587        {
588            this.Aika = aika;
589            this.Tapahtuma = tapahtuma;
590            this.lahtopaikka = new Vector(param1, param2);
591        }
592    }
593}
Note: See TracBrowser for help on using the repository browser.