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

Revision 1030, 18.7 KB checked in by anlakane, 9 years ago (diff)

Uusia kuvia. Kuvat (nyt elaimet-kansio) pitää olla saman kansion alla kuin mistä peliä ajetaan.

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