source: 2010/23/hniemi/JyTris/JyTris/Peli.cs @ 1994

Revision 1994, 22.8 KB checked in by hniemi, 8 years ago (diff)

Luotu myös puhelinversio

Line 
1using System;
2using Jypeli;
3using Jypeli.Widgets;
4using Jypeli.Assets;
5using Jypeli.WP7;
6
7namespace JyTris
8{
9    /// <summary>
10    /// JyTris 0.4
11    ///
12    /// Peli on tetrisklooni, joka on tarkoituksena toteuttaa JyPelillä
13    /// mahdollisimman yksinkertaisesti.
14    ///
15    /// Seuraavana tulossa:
16    /// - Kuvat palikoille
17    /// - Efektit palikkojen tuhoutumiseen
18    /// </summary>
19    public class Peli : Game
20    {
21        #region Muuttujat
22        private string versio = "0.5";
23
24        const int leveys = 10;
25        const int korkeus = 26;
26        const int palikkojenSivu = 30;
27
28        GameObject[][] pelikentta;
29        GameObject[][] ennustuskentta;
30        TetrisPalikka aktiivinenPalikka;
31        TetrisPalikka ennustusPalikka;
32        GameObject pausenappula;
33
34        //Liikutusvektorit
35        Vector vasemmalle = new Vector(-1, 0);
36        Vector oikealle = new Vector(1, 0);
37        Vector alas = new Vector(0, 1);
38
39
40        Timer tiputusajastin;
41
42        //Statistiikka
43        double vaikeusaste = 0.9;
44        //bool purkkabool = false;
45        IntMeter pisteet = new IntMeter(0);
46        IntMeter taso = new IntMeter(0);
47        int tuhotutRivit = 0;
48        //HighScoreList topLista;
49
50        Label tasonaytto;
51        Label pistenaytto;
52        Label status;
53
54        /*
55         * Introon tarvittavat muuttujat
56         */
57        Timer introajastin;
58        private int indeksi = 0;
59        private int suunta = 1;
60        private int vaihtoCounter = 0;
61
62        #endregion
63
64        /// <summary>
65        /// Tekee pelin alkuvalmistelut
66        /// </summary>
67        public override void Begin()
68        {
69            LuoPelikentta();
70            AlkuIntro();
71            AsetaMenuNappaimet();
72            AsetaPistelista();
73            LuoHud();
74#if WINDOWS_PHONE
75            Puhelinasetukset();
76#endif
77        }
78
79        public void AsetaPistelista()
80        {
81            //topLista = HighScoreList.LoadOrCreate("topten.dat",10);
82        }
83
84        #region WP7-Metodit
85        /// <summary>
86        /// Asettaa näytön asennon ja zoomin kohilleen.
87        /// </summary>
88        public void Puhelinasetukset()
89        {
90            Phone.DisplayOrientation = Jypeli.WP7.DisplayOrientation.Portrait;
91            Camera.ZoomToLevel();
92            Camera.Zoom(0.9);
93            Camera.Move(new Vector(40, 0));
94            TouchPanel.Listen(ButtonState.Pressed, KasitteleKosketus, null);
95        }
96
97        /// <summary>
98        /// Käsittelee pelaamiseen liittyvät kosketukset (Palikan liikuttaminen)
99        /// </summary>
100        /// <param name="b">Käsiteltävä kosketus</param>
101        public void KasitteleLiikuntaKosketukset(Touch b)
102        {
103
104            if (b.PositionOnWorld.X < AnnaKoordinaateista(aktiivinenPalikka.Sijainti()[0]).Position.X - 30)
105            {
106                Liikuta(vasemmalle);
107                return;
108            }
109            if (b.PositionOnWorld.X > AnnaKoordinaateista(aktiivinenPalikka.Sijainti()[0]).Position.X + 30)
110            {
111                Liikuta(oikealle);
112                return;
113            }
114
115            if (b.PositionOnWorld.Y < AnnaKoordinaateista(aktiivinenPalikka.Sijainti()[0]).Position.Y - 20)
116            {
117                Liikuta(alas);
118                return;
119            }
120            else if (b.PositionOnWorld.Y > AnnaKoordinaateista(aktiivinenPalikka.Sijainti()[0]).Position.Y + 10)
121            {
122                Kaanna();
123                return;
124            }
125        }
126
127        public void PysaytaPhone(Touch b)
128        {
129            Pysayta(true);
130        }
131
132        /// <summary>
133        /// Käsittelee kosketuksen menussa
134        /// </summary>
135        /// <param name="b"></param>
136        public void KasitteleKosketus(Touch b)
137        {
138            if (tiputusajastin == null)
139            {
140                KaynnistaPeli();
141                return;
142            }
143        }
144
145        public void KasittelePauseKosketus(Touch b)
146        {
147            Pysayta(false);
148        }
149        #endregion
150
151        #region Intro
152        /// <summary>
153        /// Käynnistää alkuintron
154        /// </summary>
155        void AlkuIntro()
156        {
157            introajastin = new Timer();
158            introajastin.Interval = 0.05;
159            introajastin.Trigger += IntroPyoritys;
160            introajastin.Start();
161        }
162
163        /// <summary>
164        /// Pyörittää introa
165        /// </summary>
166        /// <param name="ajastin">Ei käytössä</param>
167        void IntroPyoritys(Timer ajastin)
168        {
169            TuhoaRivi(korkeus - 1);
170
171            Color randomvari = RandomGen.NextColor();
172
173            for (int i = 0; i < pelikentta[0].Length; i++)
174            {
175                pelikentta[0][i].Color = randomvari;
176            }
177            pelikentta[0][indeksi].Color = Color.Brown;
178            indeksi += suunta;
179            vaihtoCounter++;
180            if (indeksi > leveys - 1 && suunta > 0)
181            {
182                indeksi = 0;
183            }
184            if (indeksi < 0 && suunta < 0)
185            {
186                indeksi = leveys - 1;
187            }
188            if (vaihtoCounter > 50)
189            {
190                vaihtoCounter = 0;
191                suunta = -suunta;
192            }
193        }
194
195
196        #endregion
197        #region Pelialueen ja Hudin luominen
198        /// <summary>
199        /// Luo näyttöön pistenäytöt ja muut elementit.
200        /// </summary>
201        void LuoHud()
202        {
203            Widget statistiikka = new Widget(120, 100);
204            statistiikka.Layout = new VerticalLayout();
205            Add(statistiikka);
206
207            Label pisteteksti = new Label("Pisteet:");
208            statistiikka.Add(pisteteksti);
209
210            pistenaytto = new Label();
211            pistenaytto.BindTo(pisteet);
212            statistiikka.Add(pistenaytto);
213
214            statistiikka.Position = new Vector(Level.Right + 120, Level.Top - 100);
215
216            Label tasoteksti = new Label("Taso:");
217            statistiikka.Add(tasoteksti);
218
219            tasonaytto = new Label(20, 20);
220            tasonaytto.BindTo(taso);
221            statistiikka.Add(tasonaytto);
222
223            status = new Label("JyTris " + versio);
224            Add(status);
225
226            pausenappula = new GameObject(50, 50);
227            pausenappula.Position = new Vector(Level.Right + 75, Level.Top - 25);
228            Add(pausenappula);
229
230            /*
231             * Koska ennustuskenttä on kaksiulotteinen taulukko, joudumme luomaan
232             * ensiksi taulukon sarakkeet, jotta voimme luoda rivit.
233             */
234            ennustuskentta = new GameObject[4][];
235            for (int i = 0; i < ennustuskentta.Length; i++)
236            {
237                ennustuskentta[i] = new GameObject[4];
238            }
239
240            //Tässä luodaan pelikentän "laatiko" ja sijoitetaan ne oikeille kohdilleen.
241            for (int i = 0; i < ennustuskentta.Length; i++)
242            {
243                for (int j = 0; j < ennustuskentta[i].Length; j++)
244                {
245                    ennustuskentta[i][j] = new GameObject(palikkojenSivu, palikkojenSivu, Shape.Rectangle);
246                    ennustuskentta[i][j].Color = Color.Transparent;
247                    ennustuskentta[i][j].X = Level.Right + 90 + (palikkojenSivu / 2) + j * (palikkojenSivu);
248                    ennustuskentta[i][j].Y = Level.Top - 200 - (palikkojenSivu / 2) - i * (palikkojenSivu);
249                    Add(ennustuskentta[i][j]);
250                }
251            }
252        }
253
254        /// <summary>
255        /// Asettaa ennustusnäytön näyttämään annettua palikkaa
256        /// </summary>
257        /// <param name="palikka">Näytettävä palikka</param>
258        void AsetaEnnustusnaytto(TetrisPalikka palikka)
259        {
260            for (int i = 0; i < ennustuskentta.Length; i++)
261            {
262                for (int j = 0; j < ennustuskentta[i].Length; j++)
263                {
264                    ennustuskentta[i][j].Color = Color.Transparent;
265                }
266            }
267
268            Vector[] sijainnit = palikka.Sijainti();
269            int offset = -(leveys / 2) + 1;
270
271            foreach (Vector paikka in sijainnit)
272            {
273                ennustuskentta[(int)paikka.Y][(int)paikka.X + offset].Color = palikka.Vari();
274            }
275        }
276
277        /// <summary>
278        /// Luo pelikentän ylhäällä määrätyistä vakioista
279        /// </summary>
280        void LuoPelikentta()
281        {
282            //Tässä säädetään pelialueen koko, jotta seinät tulevat oikeille kohdille
283            Level.Width = leveys * palikkojenSivu;// + leveys;
284            Level.Height = korkeus * palikkojenSivu;// + korkeus;
285            Level.CreateBorders(true);
286
287            /*
288             * Koska pelikenttä on kaksiulotteinen taulukko, joudumme luomaan
289             * ensiksi taulukon sarakkeet, jotta voimme luoda rivit.
290             */
291            pelikentta = new GameObject[korkeus][];
292            for (int i = 0; i < pelikentta.Length; i++)
293            {
294                pelikentta[i] = new GameObject[leveys];
295            }
296
297            //Tässä luodaan pelikentän "laatiko" ja sijoitetaan ne oikeille kohdilleen.
298            for (int i = 0; i < pelikentta.Length; i++)
299            {
300                for (int j = 0; j < pelikentta[i].Length; j++)
301                {
302                    pelikentta[i][j] = new GameObject(palikkojenSivu, palikkojenSivu, Shape.Rectangle);
303                    pelikentta[i][j].Color = Color.Transparent;
304                    pelikentta[i][j].X = Level.Left + (palikkojenSivu / 2) + j * (palikkojenSivu);
305                    pelikentta[i][j].Y = Level.Top - (palikkojenSivu / 2) - i * (palikkojenSivu);
306                    Add(pelikentta[i][j]);
307                }
308            }
309        }
310        #endregion
311        #region Kontrollit
312        /// <summary>
313        /// Asettaa pelin aikana tarvittavat näppäimet.
314        /// </summary>
315        void AsetaPeliNappaimet()
316        {
317            Vector vasemmalle = new Vector(-1, 0);
318            Vector oikealle = new Vector(1, 0);
319            Vector alas = new Vector(0, 1);
320
321            Keyboard.Listen(Key.Escape, ButtonState.Pressed, PeliLoppui, "Keskeyttää pelin");
322            Keyboard.Listen(Key.Left, ButtonState.Pressed, Liikuta, "Liikuttaa palikkaa vasemmalle", vasemmalle);
323            Keyboard.Listen(Key.Right, ButtonState.Pressed, Liikuta, "Liikuttaa palikkaa oikealle", oikealle);
324            Keyboard.Listen(Key.Down, ButtonState.Down, Laske, "Liikuttaa palikkaa alas", tiputusajastin);
325            Keyboard.Listen(Key.Up, ButtonState.Pressed, Kaanna, "Kääntää palikkaa");
326            Keyboard.Listen(Key.Space, ButtonState.Pressed, Tiputa, "Tiputtaa palikan");
327            Keyboard.Listen(Key.P, ButtonState.Pressed, Pysayta, "Pysayttaa pelin", true);
328            TouchPanel.Listen(ButtonState.Pressed, KasitteleLiikuntaKosketukset, null);
329            TouchPanel.ListenOn(pausenappula, ButtonState.Down, PysaytaPhone ,null);
330
331        }
332
333        void AsetaTaukoNappaimet()
334        {
335            Keyboard.Listen(Key.P, ButtonState.Pressed, Pysayta, "Jatkaa peliä", false);
336            TouchPanel.Listen(ButtonState.Pressed, KasittelePauseKosketus, null);
337        }
338
339        /// <summary>
340        /// Asettaa menuissa käytettävät näppäimet
341        /// </summary>
342        void AsetaMenuNappaimet()
343        {
344            Keyboard.Listen(Key.Escape, ButtonState.Pressed, Exit, "Poistuu pelistä");
345            Keyboard.Listen(Key.F2, ButtonState.Pressed, KaynnistaPeli, "Aloittaa uuden pelin");
346            TouchPanel.Listen(ButtonState.Pressed, KasitteleKosketus, null);
347        }
348        #endregion
349        #region Palikan siirtämiseen liittyvät
350        /// <summary>
351        /// Liikuttaa palikkaa halutun verran.
352        /// </summary>
353        /// <param name="suunta">X ja Y oltava kokonaislukuja.</param>
354        void Liikuta(Vector suunta)
355        {
356            PaivitaPalikka(aktiivinenPalikka, Color.Transparent);
357
358            if (VoikoSiirtaa(suunta, aktiivinenPalikka))
359            {
360                aktiivinenPalikka.Liikuta(suunta);
361            }
362
363            PaivitaPalikka(aktiivinenPalikka, aktiivinenPalikka.Vari());
364        }
365
366        /// <summary>
367        /// Kääntää palikkaa
368        /// </summary>
369        void Kaanna()
370        {
371            PaivitaPalikka(aktiivinenPalikka, Color.Transparent);
372
373            //Tämä kohta tarkistaa, voiko palikkaa kääntää
374            //Jos ei voi, niin poistutaan.
375            Vector[] tulevaSijainti = aktiivinenPalikka.TulevaKaanto();
376            for (int i = 0; i < tulevaSijainti.Length; i++)
377            {
378                if (!OnkoTyhja(tulevaSijainti[i]))
379                {
380                    PaivitaPalikka(aktiivinenPalikka, aktiivinenPalikka.Vari());
381                    return;
382                }
383            }
384
385            aktiivinenPalikka.Kaanna();
386            PaivitaPalikka(aktiivinenPalikka, aktiivinenPalikka.Vari());
387        }
388
389        /// <summary>
390        /// Laskee palikkaa yhdellä. Jos palikkaa ei voi laskea,
391        /// lähettää uuden palikan.
392        /// </summary>
393        /// <param name="timer">Ei käytössä</param>
394        void Laske(Timer timer)
395        {
396            PaivitaPalikka(aktiivinenPalikka, Color.Transparent);
397
398            tiputusajastin.Reset();
399            if (!VoikoSiirtaa(new Vector(0, 1), aktiivinenPalikka))
400            {
401                PaivitaPalikka(aktiivinenPalikka, aktiivinenPalikka.Vari());
402                TuhoaTaydet();
403                LuoPalikka();
404                return;
405            }
406            aktiivinenPalikka.Liikuta(new Vector(0, 1));
407            PaivitaPalikka(aktiivinenPalikka, aktiivinenPalikka.Vari());
408
409        }
410
411        /// <summary>
412        /// Tiputtaa palikkan kokonaan alas.
413        /// </summary>
414        void Tiputa()
415        {
416            TetrisPalikka palikka = aktiivinenPalikka;
417            while (aktiivinenPalikka == palikka) Laske(tiputusajastin);
418        }
419
420        /// <summary>
421        /// Tarkistaa, voiko palikalle suorittaa annetut siirrot
422        ///
423        /// Annetut siirrot siis lisätään niitä vastaaviin palikan
424        /// sijainteihin.
425        /// </summary>
426        /// <param name="siirrot">X- ja Y-arvot oltava kokonaislukuja</param>
427        /// <param name="palikka">Palikka, jonka suhteen tarkistetaan</param>
428        /// <returns>true, jos palikan siirtäminen on mahdollista</returns>
429        bool VoikoSiirtaa(Vector[] siirrot, TetrisPalikka palikka)
430        {
431            Vector[] sijainnit = palikka.Sijainti();
432
433            for (int i = 0; i < siirrot.Length; i++)
434            {
435                if (!OnkoTyhja(sijainnit[i] + siirrot[i])) return false;
436            }
437            return true;
438        }
439
440        /// <summary>
441        /// Tarkistaa voiko kaikkia palikan osia siirtää annetun
442        /// vektorin verran
443        /// </summary>
444        /// <param name="siirto">X- ja Y-arvo oltava kokonaislukuja</param>
445        /// <param name="palikka">Palikka, jonka suhteen tarkistetaan</param>
446        /// <returns>true, jos siirto on mahdollinen</returns>
447        bool VoikoSiirtaa(Vector siirto, TetrisPalikka palikka)
448        {
449            Vector[] siirrot = new Vector[4];
450            for (int i = 0; i < siirrot.Length; i++)
451            {
452                siirrot[i] = siirto;
453            }
454            return VoikoSiirtaa(siirrot, palikka);
455        }
456
457        /// <summary>
458        /// Tarkistaa, onko annetut paikka tyhjä
459        ///
460        /// Paikka on tyhjä, jos sen väri on Color.Transparent
461        /// </summary>
462        /// <param name="paikka">X ja Y oltava kokonaislukuja</param>
463        /// <returns>true, jos paikka on tyhjä</returns>
464        bool OnkoTyhja(Vector paikka)
465        {
466            if (paikka.X > leveys - 1 || paikka.X < 0) return false;
467            if (paikka.Y > korkeus - 1 || paikka.Y < 0) return false;
468
469            if (pelikentta[(int)paikka.Y][(int)paikka.X].Color == Color.Transparent) return true;
470            return false;
471        }
472
473        /// <summary>
474        /// Värittää paikkaa vastaavat laatikot annetulla värillä
475        /// </summary>
476        /// <param name="palikka">Tämän sijainti väritetään</param>
477        /// <param name="vari">Väri, jolla väritetään</param>
478        void PaivitaPalikka(TetrisPalikka palikka, Color vari)
479        {
480            Vector[] sijainnit = palikka.Sijainti();
481
482            for (int i = 0; i < sijainnit.Length; i++)
483            {
484                pelikentta[(int)sijainnit[i].Y][(int)sijainnit[i].X].Color = vari;
485            }
486        }
487
488        /// <summary>
489        /// Antaa gameobjectin, joka vastaa taulukon koordinaatteja (0,1,2...)
490        ///
491        /// Ei vastaa näytön koordinaatteja!
492        /// </summary>
493        /// <param name="koordinaatit">Haluttu koordinaatti</param>
494        /// <returns>Gameobject, joka vastaa koordinaatteja</returns>
495        GameObject AnnaKoordinaateista(Vector koordinaatit)
496        {
497            return pelikentta[(int)Math.Round(koordinaatit.Y)][(int)Math.Round(koordinaatit.X)];
498        }
499        #endregion
500        #region Pelilogiikka
501        /// <summary>
502        /// Luo palikan keskelle ylälaitaa
503        ///
504        /// Tulee antamaan satunnaisen palikan
505        /// </summary>
506        void LuoPalikka()
507        {
508            //Luo uuden palikan ja siirtää ennustuspalikan aktiiviseksi
509            //ennustusPalikka = new TetrisPalikka(leveys / 2);
510            if (aktiivinenPalikka != null)
511            {
512                aktiivinenPalikka = ennustusPalikka;
513            }
514            else
515            {
516                aktiivinenPalikka = new TetrisPalikka(leveys / 2);
517            }
518
519            ennustusPalikka = new TetrisPalikka(leveys / 2);
520
521            AsetaEnnustusnaytto(ennustusPalikka);
522
523            tiputusajastin.Reset();
524
525            Vector[] sijainnit = aktiivinenPalikka.Sijainti();
526            for (int i = 0; i < sijainnit.Length; i++)
527            {
528                if (!OnkoTyhja(sijainnit[i]))
529                {
530                    PeliLoppui();
531                    return;
532                }
533            }
534
535            PaivitaPalikka(aktiivinenPalikka, aktiivinenPalikka.Vari());
536        }
537
538        /// <summary>
539        /// Käynnistää pelin
540        ///
541        /// Luo ensimmäisen palikan ja tekee ajastimen.
542        /// Tuhoaa myös kaikki valmiina olevat palikat.
543        ///
544        /// Poistaa asetetut kontrollit ja asettaa pelikontrollit.
545        ///
546        /// Resetoi vaikeusasteen!
547        /// </summary>
548        void KaynnistaPeli()
549        {
550            status.Color = Color.Transparent;
551            status.TextColor = Color.Transparent;
552            pisteet.Value = 0;
553            taso.Value = 1;
554            tuhotutRivit = 0;
555            introajastin.Stop();
556            TuhoaKaikki();
557            ClearControls();
558            AsetaPeliNappaimet();
559
560
561            /*
562            if (purkkabool)
563            {
564                topLista.Hide();
565                purkkabool = false;
566            }
567            */
568            vaikeusaste = 0.9;
569            tiputusajastin = new Timer();
570            tiputusajastin.Interval = vaikeusaste;
571            tiputusajastin.Trigger += Laske;
572            tiputusajastin.Start();
573            LuoPalikka();
574        }
575
576        /// <summary>
577        /// Tauottaa pelin
578        ///
579        /// false-arvolla jatkaa peliä
580        /// </summary>
581        /// <param name="pysaytetaan">true, jos peli halutaan pysäyttää</param>
582        void Pysayta(bool pysaytetaan)
583        {
584            if (pysaytetaan)
585            {
586                tiputusajastin.Stop();
587                ClearControls();
588                AsetaTaukoNappaimet();
589                status.Text = "Peli pysaytetty";
590                status.TextColor = Color.Beige;
591                return;
592            }
593            status.TextColor = Color.Transparent;
594            tiputusajastin.Start();
595            ClearControls();
596            AsetaPeliNappaimet();
597        }
598
599
600        /// <summary>
601        /// Tuhoaa täydet rivit kentältä
602        /// </summary>
603        void TuhoaTaydet()
604        {
605            bool tyhjia;
606            int potti = 0;
607
608
609            for (int i = 0; i < pelikentta.Length; i++)
610            {
611                tyhjia = false;
612                for (int j = 0; j < pelikentta[i].Length; j++)
613                {
614                    if (pelikentta[i][j].Color == Color.Transparent) tyhjia = true;
615                }
616
617                if (!tyhjia)
618                {
619                    potti += 10;
620                    TuhoaRivi(i);
621                }
622            }
623
624            pisteet.Value += (potti / 10) * taso * potti;
625
626            if (tuhotutRivit > 10)
627            {
628                tuhotutRivit -= 10;
629                tiputusajastin.Interval -= 0.1;
630                taso.Value++;
631            }
632        }
633
634        /// <summary>
635        /// Tuhoaa kaikki palikat kentältä.
636        /// </summary>
637        void TuhoaKaikki()
638        {
639            //Tässä käydään lävitse kaikki laatikot ja asetetaan ne läpinäkyviksi.
640            for (int i = 0; i < pelikentta.Length; i++)
641            {
642                for (int j = 0; j < pelikentta[i].Length; j++)
643                {
644                    pelikentta[i][j].Color = Color.Transparent;
645                }
646            }
647        }
648
649        /// <summary>
650        /// Tuhoaa indeksiä vastaavan rivin ja tiputtaa sen päällä olevia rivejä.
651        /// </summary>
652        /// <param name="rivinIndeksi">Tiputettavan rivin indeksi</param>
653        void TuhoaRivi(int rivinIndeksi)
654        {
655            if (rivinIndeksi > pelikentta.Length || rivinIndeksi < 0) return;
656            tuhotutRivit++;
657
658            for (int i = rivinIndeksi; i > 0; i--)
659            {
660                for (int j = 0; j < pelikentta[i].Length; j++)
661                {
662                    pelikentta[i][j].Color = pelikentta[i - 1][j].Color;
663                }
664            }
665
666            for (int i = 0; i < pelikentta[0].Length; i++)
667            {
668                pelikentta[0][i].Color = Color.Transparent;
669            }
670        }
671
672        /// <summary>
673        /// Lopettaa pelin.
674        /// - Palikkoja ei tipu
675        /// - Poistaa vanhat kontrollit
676        /// - Asettaa menunapit toimintaan
677        /// </summary>
678        void PeliLoppui()
679        {
680            tiputusajastin.Stop();
681            status.Text = "Hävisit pelin!";
682            //status.Image = LoadImage("peliloppu");
683            status.TextColor = Color.Beige;
684            //topLista.Show(pisteet.Value);
685            //purkkabool = true;
686            ClearControls();
687            AsetaMenuNappaimet();
688        }
689        #endregion
690    }
691}
Note: See TracBrowser for help on using the repository browser.