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

Revision 955, 19.9 KB checked in by hniemi, 10 years ago (diff)

Vihollisalus lisätty, Hudia paranneltu

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;
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            vasenLaita = Level.CreateLeftBorder();
111            vasenLaita.Image = LoadImage("seina/seinaOikea");
112            vasenLaita.Angle = Angle.Degrees(270);
113
114            vasenLaita.Tag = tieto;
115            oikeaLaita = Level.CreateRightBorder();
116            oikeaLaita.Image = LoadImage("seina/seinaOikea");
117            oikeaLaita.Angle = Angle.Degrees(90);
118
119            oikeaLaita.Tag = tieto;
120            pohja = Level.CreateBottomBorder();
121            pohja.Image = LoadImage("seina/seinaOikea");
122            pohja.Angle = Angle.Degrees(0);
123            pohja.Size = new Vector(pohja.Width - 120, pohja.Height);
124
125            pohja.Tag = tieto;
126            katto = Level.CreateTopBorder();
127            katto.Image = LoadImage("seina/seinaOikea");
128            katto.Angle = Angle.Degrees(180);
129            katto.Size = new Vector(katto.Width - 120, katto.Height);
130
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        }
185
186        /// <summary>
187        /// Lataa taustalle tähdet
188        /// </summary>
189        /// <param name="kentanNumero"></param>
190        void LataaTausta(int kentanNumero)
191        {
192            tahdet = new GameObject[15];
193            for (int i = 0; i < tahdet.Length; i++)
194            {
195                GameObject tahti = new GameObject(3, 3);
196                tahti.Color = Color.White;
197                tahti.Position = new Vector(RandomGen.NextDouble(Level.Left, Level.Right),
198                                            RandomGen.NextDouble(Level.Top +20, Level.Top + 2000));
199                tahdet[i] = tahti;
200
201                Add(tahti);
202            }
203        }
204
205        /// <summary>
206        /// Luo pelaajan ja sijoittaa sen kentälle.
207        /// Asettaa pelaajalle myös aseen.
208        /// </summary>
209        void LuoPelaaja()
210        {
211            pelaajaAlus = new Alus(60, 55, 10);
212            pelaajaAlus.Shape = Shapes.Triangle;
213           
214            pelaajaAlus.Animation = new Animation(LoadImages("sankarialus/sankarialusThrust1", "sankarialus/sankarialusThrust2"));
215            pelaajaAlus.Animation.Start();
216
217            LisaData tieto;
218            tieto.Tyyppi = "oma";
219            tieto.Rajahtaa = true;
220            tieto.Damage = 5;
221            pelaajaAlus.Tag = tieto;
222
223            pelaajaAlus.Angle += Angle.Degrees(90);
224
225            pelaajaAlus.IgnoresCollisionResponse = false;
226            pelaajaAlus.Y = Level.Bottom + 40;
227            pelaajaAlus.KineticFriction = 1.0;
228            pelaajaAlus.Mass = 100000;
229
230            weapons = new Weapon[3];
231
232            weapons[0] = new Beam(1, 1);
233            ((Beam)weapons[0]).BeamCollision = AmmusOsuu;
234            weapons[0].Position = new Vector(0, -40);
235            weapons[1] = new Missile(1, 1);
236            ((Missile)weapons[1]).MissileCollision = AmmusOsuu;
237
238            weapons[2] = new Photon(1, 1);
239            ((Photon)weapons[2]).PhotonCollision = AmmusOsuu;
240
241            for (int i = 0; i < weapons.Length; i++)
242            {
243                weapons[i].IsVisible = false;
244                pelaajaAlus.Add(weapons[i]);
245            }
246
247            Add(pelaajaAlus);
248            pelaajaAlus.SetWeapon(weapons[OLETUSASE]);
249           
250            AddCollisionHandler(pelaajaAlus, PelaajaTormaa);
251        }
252
253        #endregion
254        #region Kontrollit ja liikkuminen
255        /// <summary>
256        /// Asettaa kontrollit ohjaamaan haluttua alusta
257        /// </summary>
258        /// <param name="pelaaja">Alus, jota halutaan ohjata</param>
259        void LataaKontrollit(Alus pelaaja)
260        {
261            Keyboard.Listen(Key.Escape, ButtonState.Pressed, Exit, "Lopettaa pelin");
262            Keyboard.Listen(Key.Up, ButtonState.Down, Liikuta, "Liikuttaa alusta ylös", pelaaja, nopeusPysty);
263            Keyboard.Listen(Key.Up, ButtonState.Released, pelaaja.StopVertical, null);
264            Keyboard.Listen(Key.Down, ButtonState.Down, Liikuta, "Liikuttaa alusta alas", pelaaja, -nopeusPysty);
265            Keyboard.Listen(Key.Down, ButtonState.Released, pelaaja.StopVertical, null);
266            Keyboard.Listen(Key.Left, ButtonState.Down, Liikuta, "Liikuttaa alusta vasemmalle", pelaaja, -nopeusVaaka);
267            Keyboard.Listen(Key.Left, ButtonState.Released, pelaaja.StopHorizontal, null);
268            Keyboard.Listen(Key.Right, ButtonState.Down, Liikuta, "Liikuttaa alusta oikealle", pelaaja, nopeusVaaka);
269            Keyboard.Listen(Key.Right, ButtonState.Released, pelaaja.StopHorizontal, null);
270            Keyboard.Listen(Key.LeftControl, ButtonState.Down, Ammu, "Lopettaa pelin", pelaajaAlus);
271            Keyboard.Listen(Key.D1, ButtonState.Pressed, VaihdaAsetta, "Valitsee säde-aseen", 1);
272            Keyboard.Listen(Key.D2, ButtonState.Pressed, VaihdaAsetta, "Valitsee ohjuksen", 2);
273            Keyboard.Listen(Key.D3, ButtonState.Pressed, VaihdaAsetta, "Valitsee fotoniaseen", 3);
274        }
275
276        /// <summary>
277        /// Liikuttaa alusta haluttuun suuntaan
278        /// </summary>
279        /// <param name="alus">Liikutettava alus</param>
280        /// <param name="suunta">Liikutettava suunta</param>
281        void Liikuta(Alus alus, Vector suunta)
282        {
283            if (-NOPEUS < alus.Velocity.Y && alus.Velocity.Y < NOPEUS && suunta.Y != 0)
284            {
285                alus.Velocity += suunta;
286            }
287            if (-NOPEUS < alus.Velocity.X && alus.Velocity.X < NOPEUS && suunta.X != 0)
288            {
289                alus.Velocity += suunta;
290            }
291        }
292
293        void VaihdaAsetta(int aseenNumero)
294        {
295            if (aseenNumero > 0 && aseenNumero < 4)
296            {
297                pelaajaAlus.SetWeapon(weapons[aseenNumero-1]);
298                for (int i = 0; i < aseNimet.Length; i++)
299                {
300                    aseNimet[i].TextColor = Color.White;
301                }
302                aseNimet[aseenNumero-1].TextColor = Color.Yellow;
303            }
304        }
305
306        /// <summary>
307        /// Ampuu aluksella
308        /// </summary>
309        /// <param name="alus">Alus joka ampuu</param>
310        void Ammu(Alus alus)
311        {
312            alus.Shoot();
313        }
314
315        #endregion
316        #region Viholliset
317        /// <summary>
318        /// Lataa viholliset
319        /// TODO: Kentän numeron huomioiminen
320        /// </summary>
321        void LataaViholliset(int maara, double min, double max)
322        {
323            List<AikaTapahtuma> vihollistenTuloajat = new List<AikaTapahtuma>();
324           
325            for (int i = 0; i < maara; i++)
326            {
327                vihollistenTuloajat.Add(new AikaTapahtuma(2 + (i * 5), LahetaSatunnainenVihollislaivue, 4, 10));
328            }
329            vihollistenTuloajat.Add(new AikaTapahtuma(2 + (maara * 5), LahetaLoppupomo, 1, 20));
330
331            foreach (AikaTapahtuma tapahtuma in vihollistenTuloajat)
332            {
333                Timer ajastin = new Timer();
334                ajastin.Tag = tapahtuma.Lahtopaikka;
335                ajastin.Interval = tapahtuma.Aika;
336                ajastin.Trigger += tapahtuma.Tapahtuma;
337                Add(ajastin);
338                ajastin.Start(1);
339            }
340        }
341
342        /// <summary>
343        /// Luo alukset ja lähettää ne matkaan
344        /// </summary>
345        /// <param name="sender">Timerin tagissa on lähtökoordinaatti</param>
346        /// <param name="lahetysX">X-koordinaatti, josta muodostelma lähtee</param>
347        void LahetaLoppupomo(Timer sender)
348        {
349            double taso = ((Vector)sender.Tag).X;
350
351            List<Alus> alukset = new List<Alus>();
352            Image vihollisenKuva = LoadImage("loppuvastus" + 1);
353            alukset.Add(LuoVihollinen(vihollisenKuva, 400));
354            alukset[0].Position = new Vector(0, Level.Top + 200);
355            alukset[0].Angle = Angle.Degrees(270);
356            Add(alukset[0]);
357
358            //Aseen säätö
359            Photon ase = new Photon(10, 10);
360            LisaData ammuksenData;
361            ammuksenData.Damage = 20;
362            ammuksenData.Rajahtaa = false;
363            ammuksenData.Tyyppi = "vihollinen";
364            ase.Tag = ammuksenData;
365            alukset[0].Add(ase);
366            alukset[0].SetWeapon(ase);
367            alukset[0].UsedWeapon.IsVisible = false;
368            ase.PhotonCollision = AmmusOsuu;
369
370            Timer ampumaAjastin = new Timer();
371            ampumaAjastin.Interval = 0.7;
372            ampumaAjastin.Trigger += alukset[0].Shoot;
373            Add(ampumaAjastin);
374            ampumaAjastin.Start();
375
376            List<Vector> reitti = new List<Vector>();
377            reitti.Add(new Vector(-200, Level.Top - 100 ));
378            reitti.Add(new Vector(200, Level.Top - 100));
379
380            Muodostelma muodostelma = new Muodostelma(alukset, reitti, LuoLahettaja());
381            muodostelma.MovingSpeed = 100;
382            muodostelma.Start();
383        }
384
385        /// <summary>
386        /// Arpoo ja lähettää satunnaisen vihollislaivueen
387        /// Laivueessa on tällä hetkellä 10 alusta
388        /// Aluksen kuva arvotaan tiedostoista, joiden nimi on "vihollinen#.png"
389        /// </summary>
390        /// <param name="sender"></param>
391        void LahetaSatunnainenVihollislaivue(Timer sender)
392        {
393            List<Alus> alukset = new List<Alus>();
394            Image vihollisenKuva = LoadImage("vihollinen" + RandomGen.NextInt(1,VIHOLLISKUVIA));
395
396            int min = (int)((Vector)sender.Tag).X;
397            int max = (int)((Vector)sender.Tag).Y;
398            int koko = RandomGen.NextInt(min, max);
399
400            for (int i = 0; i < koko; i++)
401            {
402                alukset.Add(LuoVihollinen(vihollisenKuva, 40));
403                Add(alukset[i]);
404                Angle alas = new Angle();
405                alas.Degree = 270;
406                alukset[i].Angle = Angle.Degrees(270);
407                alukset[i].Position = new Vector(0, Level.Top + 200);
408                AddCollisionHandler(alukset[i], VihollinenTormaa);
409            }
410
411            List<Vector> reitti = ArvoReitti(RandomGen.NextInt(0,5));
412            Muodostelma muodostelma = new Muodostelma(alukset, reitti, LuoLahettaja());
413            muodostelma.MovingSpeed = 100;
414            muodostelma.Start();
415        }
416
417        /// <summary>
418        /// Arpoo koneelle reitin, joka lähteee ylhäältä ja päätyy alas
419        /// </summary>
420        /// <param name="valipisteet">Välipisteiden määrä, 0 -></param>
421        /// <returns></returns>
422        List<Vector> ArvoReitti(int valipisteet)
423        {
424            List<Vector> reitti = new List<Vector>();
425            reitti.Add(new Vector(RandomGen.NextDouble(Level.Left + 30, Level.Right - 30),Level.Top + 80));
426            for (int i = 0; i < valipisteet; i++)
427            {
428                reitti.Add(new Vector(RandomGen.NextDouble(Level.Left + 30, Level.Right - 30),
429                                     (RandomGen.NextDouble(Level.Bottom + 30, Level.Top - 100))));
430            }
431            reitti.Add(new Vector(RandomGen.NextDouble(Level.Left + 30, Level.Right - 30), Level.Bottom - 35));
432            return reitti;
433        }
434
435        Alus LuoVihollinen(Image kuva, int hp)
436        {
437           
438            Alus vihollinen = new Alus(kuva.Width/5, kuva.Height/5, hp);
439            vihollinen.Image = kuva;
440            LisaData tieto;
441            tieto.Tyyppi = "vihollinen";
442            tieto.Rajahtaa = true;
443            tieto.Damage = 5;
444            vihollinen.Tag = tieto;
445            return vihollinen;
446        }
447
448        /// <summary>
449        /// Luo ajastimen
450        /// Lisää myös ajastimen, joten voidaan kutsua suoraan Muodostelman muodostajassa.
451        /// </summary>
452        /// <returns></returns>
453        Timer LuoLahettaja()
454        {
455            Timer ajastin = new Timer();
456            ajastin.Interval = 0.5;
457            Add(ajastin);
458            return ajastin;
459        }
460        #endregion
461        #region Tapahtumat
462        /// <summary>
463        /// Pelaajan törmäyksen käsittelijä
464        ///
465        /// Katsoo myös, että pelaaja ei juutu seiniin
466        /// </summary>
467        /// <param name="tormaaja"></param>
468        /// <param name="kohde"></param>
469        void PelaajaTormaa(PhysicsObject tormaaja, PhysicsObject kohde)
470        {
471            if (((LisaData)kohde.Tag).Tyyppi == "vihollinen") 
472            {
473                ((Alus)tormaaja).TakeHit(5);
474                if (kohde is Alus) ((Alus)kohde).TakeHit(20);
475            }
476
477            if (kohde == vasenLaita)
478            {
479                tormaaja.X = Level.Left + tormaaja.Height / 2 + 1;
480                tormaaja.StopHorizontal();
481            }
482
483            if (kohde == oikeaLaita)
484            {
485                tormaaja.X = Level.Right - tormaaja.Height / 2 - 1;
486                tormaaja.StopHorizontal();
487            }
488            if (kohde == katto)
489            {
490                tormaaja.Y = Level.Top - tormaaja.Width / 2 - 1;
491                tormaaja.StopVertical();
492            }
493            if (kohde == pohja)
494            {
495                tormaaja.Y = Level.Bottom + tormaaja.Width/2 +1;
496                tormaaja.StopVertical();
497            }
498
499        }
500
501        /// <summary>
502        /// Mitä tapahtuu, kun vihollinen tulee ns. poistumisalueelle
503        /// </summary>
504        /// <param name="tormaaja"></param>
505        /// <param name="kohde"></param>
506        void VihollinenTormaa(PhysicsObject tormaaja, PhysicsObject kohde)
507        {
508            if (kohde == exitZone) Remove(tormaaja);
509           
510        }
511
512        void AmmusOsuu(PhysicsObject ammus, PhysicsObject toinen)
513        {
514
515            if (toinen.Tag.ToString() == "seina" || ((LisaData)toinen.Tag).Tyyppi != ((LisaData)ammus.Tag).Tyyppi)
516            {
517                ammus.Destroy();
518                if (((LisaData)ammus.Tag).Rajahtaa)
519                {
520                    Explosion rajahdys = new Explosion(100);
521                    rajahdys.Position = toinen.Position;
522                    Add(rajahdys);
523                }
524
525                if (((LisaData)toinen.Tag).Tyyppi == "vihollinen")
526                {
527                    if (toinen is Alus) 
528                    {
529                        ((Alus)toinen).TakeHit(((LisaData)ammus.Tag).Damage);
530                        if (toinen.IsDestroyed()) score.Value += 300;
531                    }
532                   
533                }
534            }
535
536
537        }
538        #endregion
539    }
540
541    public class AikaTapahtuma 
542    {
543        public int Aika;
544        public Timer.TriggerHandler Tapahtuma;
545        private Vector lahtopaikka;
546
547        public Vector Lahtopaikka
548        {
549            get{ return lahtopaikka; }
550        }
551
552        public AikaTapahtuma(int aika, Timer.TriggerHandler tapahtuma, double param1, double param2)
553        {
554            this.Aika = aika;
555            this.Tapahtuma = tapahtuma;
556            this.lahtopaikka = new Vector(param1, param2);
557        }
558    }
559}
Note: See TracBrowser for help on using the repository browser.