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

Revision 1539, 18.9 KB checked in by hniemi, 11 years ago (diff)

Näyttöelementit laitettu widgettiin ja tekstit lisätty

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