source: 2010/23/hniemi/ShootEmUp/ShootEmUp/Peli.cs @ 993

Revision 993, 20.4 KB checked in by hniemi, 12 years ago (diff)

Luotu uus abstraktiluokka helpottamaan aseiden tekemistä
Aseiden vaihtoa myös muokattu hieman ja lisätty pyhä purkkakorjaus.

Aiemmasta poisjääneet seinät myös lisätty mukaan.

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