source: 2010/24/anlakane/Muistipeli/Muistipeli.cs @ 1029

Revision 1029, 18.9 KB checked in by anlakane, 13 years ago (diff)

Refaktorointia ja pelipisteitä.

Line 
1using System;
2using System.IO;
3using System.Collections.Generic;
4using Jypeli;
5using Jypeli.Widgets;
6using Jypeli.ScreenObjects;
7using Jypeli.Assets;
8using Jypeli.Effects;
9
10
11namespace Muistipeli
12{
13    public struct Paikka
14    {
15        public int Rivi;
16        public int Sarake;
17
18        public Paikka(int rivi, int sarake)
19        {
20            Rivi = rivi;
21            Sarake = sarake;
22        }
23    }
24
25    public struct Pelaaja
26    {
27        public int Numero;
28        public String Nimi;
29        public int Pisteet;
30
31        public Pelaaja(String nimi, int numero)
32        {
33            Numero = numero;
34            Nimi = nimi;
35            Pisteet = 0;
36        }
37    }
38
39
40    public class Muistipeli : Game
41    {
42        int montakoRivia;
43        int montakoSaraketta;
44
45        double korttienVali = 20.0;
46        double kortinLeveys = 50;
47        double kortinKorkeus = 70;
48
49        Kortti[,] kortit; // rivit, sarakkeet
50        Paikka korostettuKortti;
51        int montakoKorttia;
52        int[] montakoKutakinKorttitunnusta;
53
54        public enum Suunta { Vasen, Oikea, Ylos, Alas }
55        Suunta mihinSuuntaanMenossa;
56
57        GameObject highlighter;
58        List<Kortti> kaannetyt; // Yhdellä vuorolla käännetyt kortit. Tyhjennetään vuoron päätteeksi. Listassa voi olla siis 0, 1 tai 2 alkiota.
59        Timer piilotusAjastin;
60        const double aikaaEnnenPiilottamista = 2;
61
62        Pelaaja pelaaja1;
63        Pelaaja pelaaja2;
64        Pelaaja vuorossaOlevaPelaaja;
65        Label vuoronaytto;
66
67        IntMeter pelaajan1Pisteet;
68        IntMeter pelaajan2Pisteet;
69        IntMeter korttejaLoydetty;
70
71        protected override void Begin()
72        {
73            montakoKorttia = 16; // Pitää olla ennen laskureiden lisäämistä
74            LisaaPelaajat(2);
75
76            AloitaUusiPeli();
77
78        }
79
80        public void AloitaUusiPeli()
81        {
82            ClearAll();
83            LisaaPiilotusajastin();
84            //LisaaKuvat();
85            LisaaLaskurit();
86            LisaaVuoronaytto();
87
88            montakoKutakinKorttitunnusta = new int[montakoKorttia / 2]; // kortin tunnusNro indeksistä, alkiot tulkitaan siten että "montako tämän tunnuksen alkiota on lisätty peliin"
89            kaannetyt = new List<Kortti>();
90
91            // Laitetaan ensin rivejä ja sarakkeita yhtä paljon
92            montakoSaraketta = (int)Math.Sqrt(montakoKorttia);
93            // Kortit vähän mukavempaan muotoon, koska näytöt on yleensä leveämpiä kuin korkeita
94            montakoSaraketta = (int)Math.Floor((3.0 / 2.0) * montakoSaraketta);
95            // Tarvittavien rivien määrä saadaan korttien määrän ja saadun sarakkeiden määrän suhteesta
96            montakoRivia = (int)Math.Ceiling((double)montakoKorttia / (double)montakoSaraketta);
97            kortit = new Kortti[montakoRivia, montakoSaraketta];
98            KortitRuudulle(montakoKorttia);
99            LisaaHighLighter();
100
101            // Laitetaan kenttä sopivan kokoiseksi että kortit täyttävät aina mahollisimman paljon ruutukapasiteetista
102            Level.Width = montakoSaraketta * (korttienVali + kortinLeveys) + kortinLeveys;
103            Level.Height = montakoRivia * (korttienVali + kortinKorkeus) + kortinKorkeus;
104            Camera.ZoomToLevel();
105
106            PeliKayntiin();
107            AsetaNappaimet();
108
109        }
110
111        public void LisaaPiilotusajastin()
112        {
113            piilotusAjastin = new Timer();
114            piilotusAjastin.Interval = aikaaEnnenPiilottamista;
115            piilotusAjastin.Trigger += PiilotaKaannetyt;
116            Add(piilotusAjastin);
117        }
118
119        public void LisaaLaskurit()
120        {
121            pelaajan1Pisteet = new IntMeter(0);
122            Label p1teksti = new Label("Pelaaja 1 pisteet: ");
123            Label pisteNaytto1 = new Label();
124            Label p1VoitotTeksti = new Label("Pelaaja 1 voitot: ");
125            Label p1Voitot = new Label(pelaaja1.Pisteet.ToString());
126
127            p1teksti.TextColor = Color.Black;
128            p1teksti.Position = new Vector(Screen.Left + 140, Screen.Bottom + 70);
129            pisteNaytto1.Position = new Vector(p1teksti.X + (p1teksti.Width/2) + 10, p1teksti.Y);
130            pisteNaytto1.TextColor = Color.Blue;
131            pisteNaytto1.BindTo(pelaajan1Pisteet);
132            p1VoitotTeksti.Position = new Vector(Screen.Left + 140 - ((p1teksti.Width - p1VoitotTeksti.Width)/2), p1teksti.Y - 30);
133            p1Voitot.Position = new Vector(p1VoitotTeksti.X + (p1VoitotTeksti.Width / 2) + 10, p1VoitotTeksti.Y);
134
135            Add(p1teksti);
136            Add(pisteNaytto1);
137            Add(p1VoitotTeksti);
138            Add(p1Voitot);
139
140            pelaajan2Pisteet = new IntMeter(0); 
141            Label p2teksti = new Label("Pelaaja 2 pisteet: ");
142            Label pisteNaytto2 = new Label();
143            Label p2VoitotTeksti = new Label("Pelaaja 1 voitot: ");
144            Label p2Voitot = new Label(pelaaja2.Pisteet.ToString());
145
146            p2teksti.TextColor = Color.Black;
147            p2teksti.X = Screen.Right- 140;
148            p2teksti.Y = Screen.Bottom + 70;
149            pisteNaytto2.X = p2teksti.X + (p2teksti.Width / 2) + 10;
150            pisteNaytto2.Y = p2teksti.Y;
151            pisteNaytto2.TextColor = Color.Red;
152            pisteNaytto2.BindTo(pelaajan2Pisteet);
153            p2VoitotTeksti.X = Screen.Right - 140 + ((p2teksti.Width - p2VoitotTeksti.Width) / 2);
154            p2VoitotTeksti.Y = p2teksti.Y - 30;
155            p2Voitot.Position = new Vector(p2VoitotTeksti.X + (p2VoitotTeksti.Width / 2) + 10, p2VoitotTeksti.Y);
156
157            Add(p2teksti);
158            Add(pisteNaytto2);
159            Add(p2VoitotTeksti);
160            Add(p2Voitot);
161
162            korttejaLoydetty = new IntMeter(0);
163            korttejaLoydetty.MaxValue = montakoKorttia;
164            korttejaLoydetty.UpperLimit += KaikkiLoydetty;
165        }
166
167        public void KaikkiLoydetty(int arvo)
168        {
169            Mouse.IsCursorVisible = true;
170            String voittoteksti;
171            if (pelaajan1Pisteet > pelaajan2Pisteet)
172            {
173                voittoteksti = "Pelaaja 1 voitti! ";
174                pelaaja1.Pisteet++;
175            }
176            else if (pelaajan2Pisteet > pelaajan1Pisteet)
177            {
178                voittoteksti = "Pelaaja 2 voitti! ";
179                pelaaja2.Pisteet++;
180            }
181            else
182            {
183                voittoteksti = "Tasapeli! ";
184            }
185
186            MessageBox m = new MessageBox(
187                "Peli päättyi", 
188                "" + voittoteksti + "Aloita uusi peli painamalla OK.");
189            m.OkButton.Clicked += OKPainettu;
190            Add(m);
191        }
192
193        public void OKPainettu()
194        {
195            AloitaUusiPeli();
196        }
197
198        public void LisaaVuoronaytto()
199        {
200            Label vuorossaNyt = new Label("Vuorossa nyt");
201            vuorossaNyt.X = 0;
202            vuorossaNyt.Y = Screen.Bottom + 70;
203            vuoronaytto = new Label();
204            vuoronaytto.X = 0;
205            vuoronaytto.Y = vuorossaNyt.Y - 30;           
206            Add(vuorossaNyt);
207            Add(vuoronaytto);
208        }
209
210        /// <summary>
211        /// Korostetaan ensimmäinen kortti.
212        /// </summary>
213        public void PeliKayntiin()
214        {
215            korostettuKortti = new Paikka(0, 0);
216            KorostaKortti(new Paikka(0, 0));
217            vuorossaOlevaPelaaja = pelaaja1;
218            vuoronaytto.Text = "Pelaaja 1";
219            MessageDisplay.Add("Pelaaja 1 aloittaa pelin!");
220        }
221
222        void LisaaHighLighter()
223        {
224            highlighter = new GameObject(kortinLeveys, kortinKorkeus);
225            highlighter.Image = LoadImage("highlight1");
226            Add(highlighter);
227        }
228
229        private void LisaaKuvat()
230        {
231            List<String> kuvat = new List<string>();
232            String[] kuvatiedostot = Directory.GetFiles("Content");
233            char[] erottimet = new char[] { '\\', '.' };
234            foreach (var kuva in kuvatiedostot)
235            {
236                String[] splitattu = kuva.Split(erottimet);
237                if (splitattu.Length > 1)
238                {
239                    if (splitattu[1] != "highlight" && splitattu[1] != "taka")
240                        kuvat.Add(splitattu[1]);
241                }
242            }
243        }
244
245        void LisaaPelaajat(int montakoPelaajaa)
246        {
247            // Toistaiseksi tehdään "manuaalisesti" kaksi pelaajaa
248            pelaaja1 = new Pelaaja("", 1);
249            pelaaja2 = new Pelaaja("", 2);
250        }
251
252        void AsetaNappaimet()
253        {
254            Keyboard.Listen(Key.Left, ButtonState.Pressed, KortinValinta, null, Suunta.Vasen);
255            Keyboard.Listen(Key.Right, ButtonState.Pressed, KortinValinta, null, Suunta.Oikea);
256            Keyboard.Listen(Key.Up, ButtonState.Pressed, KortinValinta, null, Suunta.Ylos);
257            Keyboard.Listen(Key.Down, ButtonState.Pressed, KortinValinta, null, Suunta.Alas);
258            Keyboard.Listen(Key.Space, ButtonState.Pressed, KaannaKortti, null);
259            Keyboard.Listen(Key.Escape, ButtonState.Pressed, Lopeta, null);
260        }
261
262        void Lopeta()
263        {
264            Exit();
265        }
266
267        void KaannaKortti()
268        {
269            if (VoikoKorttiaKaantaa(kortit[korostettuKortti.Rivi, korostettuKortti.Sarake]))
270            {
271                kortit[korostettuKortti.Rivi, korostettuKortti.Sarake].Kaanna();
272                kaannetyt.Add(kortit[korostettuKortti.Rivi, korostettuKortti.Sarake]);
273
274                if (kaannetyt.Count == 2) // Tasan kaksi korttia käännetään yhdellä vuorolla
275                {
276                    if (kaannetyt[0].Tunniste == kaannetyt[1].Tunniste) // Käännetyt kortit muodostavat parin
277                    {
278                        foreach (Kortti kaannetty in kaannetyt)
279                        {
280                            RajaytaKortti(kaannetty);
281                            kaannetty.PoistettuPelista = true;
282                        }
283                        PariLoytyi();
284                    }
285                    else
286                    {
287                        // Jos kaksi korttia on käännetty niin ajastin lähtee käyntiin eikä sinä aikana voi kääntää kortteja
288                        Keyboard.Disable(Key.Space);
289                        piilotusAjastin.Start();
290                    }
291                }
292            }
293        }
294
295        public void PariLoytyi()
296        {
297            MediaPlayer.Play("tada");
298            kaannetyt.Clear();
299
300            if (vuorossaOlevaPelaaja.Equals(pelaaja1))
301            {
302                pelaajan1Pisteet.Value++;
303            }
304            else if (vuorossaOlevaPelaaja.Equals(pelaaja2))
305            {
306                pelaajan2Pisteet.Value++;
307            }
308
309            korttejaLoydetty.Value += 2;
310        }
311
312        /// <summary>
313        /// Näpsäkkä korttiin kohdistettu "räjähdys" tai mikä efekti lie.
314        /// </summary>
315        /// <param name="kaannetty">Kortti jonka päälle räjähdys tulee.</param>
316        public void RajaytaKortti(Kortti kortti)
317        {
318            Image i = kortti.KuvaPuoliTekstuuri;
319            ExplosionSystem e = new ExplosionSystem(i, 10);
320            e.MinLifetime = 0.3;
321            e.MaxLifetime = 1.5;
322            e.MinVelocity = 1;
323            e.MaxVelocity = 300;
324            e.MinScale = 0.01;
325            e.MaxScale = 0.05;
326            Add(e);
327            e.AddEffect(kortti.Position.X, kortti.Position.Y, 10);
328        }
329
330        public void VuoroVaihtuu()
331        {
332            if (vuorossaOlevaPelaaja.Equals(pelaaja1))
333            {
334                vuorossaOlevaPelaaja = pelaaja2;
335                highlighter.Image = LoadImage("highlight2");
336                vuoronaytto.Text = "Pelaaja 2";
337                return;
338            }
339
340            if (vuorossaOlevaPelaaja.Equals(pelaaja2))
341            {
342                vuorossaOlevaPelaaja = pelaaja1;
343                highlighter.Image = LoadImage("highlight1");
344                vuoronaytto.Text = "Pelaaja 1"; 
345                return;
346            }
347        }
348
349        public bool VoikoKorttiaKaantaa(Kortti kortti)
350        {
351            // Ei käännetä kahta kertaa samaa korttia
352            if (kaannetyt.Count == 0 || kortit[korostettuKortti.Rivi, korostettuKortti.Sarake] != kaannetyt[0])
353            {
354                // Jos kortti "on jo löydetty", niin sitä ei voi missään tapauksessa kääntää
355                bool onkoPoistettuPelista = kortit[korostettuKortti.Rivi, korostettuKortti.Sarake].PoistettuPelista;
356
357                if (!onkoPoistettuPelista)
358                {
359                    return true;
360                }
361            }
362            return false;
363        }
364
365        void PiilotaKaannetyt(Timer t)
366        {
367            foreach (var item in kaannetyt)
368            {
369                item.Kaanna();
370            }
371            kaannetyt.Clear();
372            piilotusAjastin.Stop();
373            Keyboard.Enable(Key.Space);
374            VuoroVaihtuu();
375        }
376
377        void KorostaKortti(Paikka korostettavaKortti)
378        {
379            korostettavaKortti = TarkistaKortinNro(korostettavaKortti);
380            highlighter.Position = new Vector(KortinX(korostettavaKortti.Sarake), KortinY(korostettavaKortti.Rivi));
381            Kortti.PuoliEsilla puoliesilla = kortit[korostettavaKortti.Rivi, korostettavaKortti.Sarake].KumpiPuoliEsilla();
382            korostettuKortti = korostettavaKortti;
383        }
384
385        /// <summary>
386        /// Aliohjelma pitää huolen, että valittu kortti on aina
387        /// rivi- ja sarakeindeksien sisäpuolella. Toisin sanoen
388        /// rivistä/sarakkeesta "yli" hypättäessä kursori palautuu
389        /// oikeaan paikkaan.
390        /// </summary>
391        /// <param name="kortinNro">Kortin rivi, sarake</param>
392        /// <returns>"Korjatut" koordinaatit</returns>
393        private Paikka TarkistaKortinNro(Paikka paikka)
394        {
395            // Viimeisen rivin jälkeen palataan ensimmäiselle riville
396            if (paikka.Rivi >= montakoRivia)
397                paikka.Rivi = 0;
398
399            // Viimeisen sarakkeen jälkeen palataan ensimmäiseen sarakkeeseen
400            if (paikka.Sarake >= montakoSaraketta)
401                paikka.Sarake = 0;
402
403            // Ensimmäisestä rivistä "taaksepäin" liikuttaessa
404            // hypätään viimeiselle riville
405            if (paikka.Rivi < 0)
406                paikka.Rivi = montakoRivia - 1;
407
408            // Ensimmäisestä sarakkeesta "taaksepäin" liikuttaessa
409            // hypätään viimeiseen sarakkeeseen
410            if (paikka.Sarake < 0)
411                paikka.Sarake = montakoSaraketta - 1;
412
413            // Mentiin pelipakan "tyhjälle alueelle"
414            if (kortit[paikka.Rivi, paikka.Sarake] == null)
415                paikka = TultiinNullViitteeseen(paikka);
416
417            return paikka;
418        }
419
420        private Paikka TultiinNullViitteeseen(Paikka kortinPaikka)
421        {
422            if (mihinSuuntaanMenossa == Suunta.Vasen)
423                return new Paikka(kortinPaikka.Rivi, (montakoKorttia % montakoSaraketta) - 1);
424            if (mihinSuuntaanMenossa == Suunta.Oikea)
425                return new Paikka(kortinPaikka.Rivi, 0);
426            if (mihinSuuntaanMenossa == Suunta.Ylos)
427                return new Paikka(montakoRivia - 2, kortinPaikka.Sarake);
428
429            // alas
430            return new Paikka(0, kortinPaikka.Sarake);
431        }
432
433        void KortinValinta(Suunta suunta)
434        {
435            mihinSuuntaanMenossa = suunta;
436            if (mihinSuuntaanMenossa == Suunta.Vasen)
437                KorostaKortti(new Paikka(korostettuKortti.Rivi, korostettuKortti.Sarake - 1));
438
439            if (mihinSuuntaanMenossa == Suunta.Oikea)
440                KorostaKortti(new Paikka(korostettuKortti.Rivi, korostettuKortti.Sarake + 1));
441
442            if (mihinSuuntaanMenossa == Suunta.Ylos)
443                KorostaKortti(new Paikka(korostettuKortti.Rivi - 1, korostettuKortti.Sarake));
444
445            if (mihinSuuntaanMenossa == Suunta.Alas)
446                KorostaKortti(new Paikka(korostettuKortti.Rivi + 1, korostettuKortti.Sarake));
447        }
448
449        /// <summary>
450        /// Aliohjelma lisää halutun määrän kortteja
451        /// taulukkoon ja edelleen ruudulle.
452        /// </summary>
453        /// <param name="montakoKorttiaLisataan">Kuinka monta korttia taulukkoon (attribuutti) lisätään.</param>
454        void KortitRuudulle(int montakoKorttiaLisataan)
455        {
456            int montakoKorttiaLisatty = 0;
457
458            for (int r = 0; r < kortit.GetLength(0); r++) // Rivit
459            {
460                for (int s = 0; s < kortit.GetLength(1); s++) // Sarakkeet
461                {
462                    // Jos tarvittava määrä kortteja on lisätty,
463                    // laitetaan loppuihin taulukon alkioihin null-viite
464                    if (montakoKorttiaLisataan == montakoKorttiaLisatty)
465                    {
466                        kortit[r, s] = null;
467                        continue;
468                    }
469
470                    kortit[r, s] = TeeKortti("kortti1");
471                    kortit[r, s].KuvaPuoliTekstuuri = LoadImage("henkilo" + kortit[r, s].Tunniste.ToString());
472                    Add(kortit[r, s]);
473
474                    //Label tunnusTeksti = new Label();
475                    //tunnusTeksti.Text = kortit[r, s].Tunniste.ToString();
476                    //tunnusTeksti.TextColor = Color.White;
477                    //Add(tunnusTeksti);
478
479                    kortit[r, s].X = KortinX(s);
480                    kortit[r, s].Y = KortinY(r);
481                    //tunnusTeksti.Position = new Vector(kortit[r, s].X, kortit[r, s].Y);
482                    montakoKorttiaLisatty++;
483                }
484            }
485        }
486
487        public double KortinX(int sarake)
488        {
489            return (-(montakoSaraketta * (kortinLeveys + korttienVali)) / 2) + (sarake * (kortinLeveys + korttienVali)) + korttienVali;
490        }
491
492        public double KortinY(int rivi)
493        {
494            // Viimeinen termi tulee siitä että viimeisen kortin perässä ei tarvita välistystä
495            return ((montakoRivia) * (kortinKorkeus + korttienVali)) / 2 - rivi * (kortinKorkeus + korttienVali) - korttienVali;
496        }
497
498        public Kortti TeeKortti(String kortinKuva)
499        {
500            Image kuvaTekstuuri = LoadImage(kortinKuva);
501            Image takaTekstuuri = LoadImage("taka");
502            Kortti kortti = new Kortti(kortinLeveys, kortinKorkeus, false, kuvaTekstuuri, takaTekstuuri, 0);
503            int tunnus;
504            while (true)
505            {
506                tunnus = RandomGen.NextInt(0, montakoKutakinKorttitunnusta.Length - 1);
507                if (montakoKutakinKorttitunnusta[tunnus] < 2)
508                {
509                    montakoKutakinKorttitunnusta[tunnus]++;
510                    break;
511                }
512            }
513
514            return new Kortti(kortinLeveys, kortinKorkeus, false, kuvaTekstuuri, takaTekstuuri, tunnus);
515        }
516    }
517}
Note: See TracBrowser for help on using the repository browser.