source: 2013/30/MiskaK/MW2(My Warfare 2)/MW2(My Warfare 2)/MW2(My Warfare 2)/MW2_My_Warfare_2_.cs @ 4677

Revision 4677, 117.7 KB checked in by anlakane, 7 years ago (diff)

Korjattu kopteri. Tehty uutta Escape-pelimuotoa ja lisätty sille valikko. Lisätty deathmatchiin vaihtoehtoinen teema.

Line 
1// MY WARFARE 2
2// ohjelmointi: Miska Kananen
3// tekstuurit: Miska Kananen, Leevi Kujanpää, Kalle Pienmäki
4// musiikit: Kalle Pienmäki
5
6using System;
7using System.Collections.Generic;
8using System.Text;
9using Jypeli;
10using Jypeli.Assets;
11using Jypeli.Controls;
12using Jypeli.Effects;
13using Jypeli.Widgets;
14using XnaPathfidingLibrary;
15using My_Warfare_2_Server;
16
17/// @author Miska Kananen
18/// @version 22.6.2013
19///
20/// <summary>
21/// My Warfare 2:n pääluokka. Peli toimii tämän luokan sisällä.
22/// </summary>
23public class MW2_My_Warfare_2_ : PhysicsGame
24{
25    #region attribuutit, kuvat ja äänet
26    #region peliattribuutit
27
28    public static MW2_My_Warfare_2_ Peli { get; private set; }
29    public Pelaaja[] pelaajat = new Pelaaja[Vakiot.PELAAJIEN_MAARA];
30    private List<GameObject> tehosteet = new List<GameObject>();
31    private Kentta KentanOsat { get; set; }
32    private String ValittuKenttaTiedosto { get; set; }
33    private Timer AikaKentanAlusta = new Timer();
34
35    /// <summary>
36    /// Onko klassinen vai satunnainen kenttä.
37    /// </summary>
38    private bool OnkoSatunnaisKentta = false;
39
40    /// <summary>
41    /// Monestako taposta voittaa pelin.
42    /// </summary>
43    public static IntMeter MonestakoVoittaa = new IntMeter(Int32.MaxValue);
44
45    /// <summary>
46    /// Kauanko Escapessa puolustetaan kopteria.
47    /// </summary>
48    public static DoubleMeter KauankoPuolustetaan = new DoubleMeter(120.0);
49
50    // Tämä attribuuttikönttä POIS
51    Label ammusmittariNäyttö;
52    Label ammusmittariNäyttö2;
53    // -------------------
54
55    static readonly SoundEffect aseTyhjäAani = LoadSoundEffect("dry-fire-gun");
56    static readonly SoundEffect aseLatausAani = LoadSoundEffect("Pump Shotgun");
57    static readonly SoundEffect lippaanPoistoAani = LoadSoundEffect("clip-remove");
58    static readonly SoundEffect hylsynPutoamisAani = LoadSoundEffect("gun_shell_drop");
59    static readonly SoundEffect luotiOsuu = LoadSoundEffect("bullet_hit");
60    static readonly SoundEffect luotiOsuu2 = LoadSoundEffect("bullet_hit2");
61    static readonly SoundEffect luotiOsuu3 = LoadSoundEffect("bullet_hit3");
62    static readonly SoundEffect luotiOsuu4 = LoadSoundEffect("bullet_hit4");
63    static readonly SoundEffect luotiOsuu5 = LoadSoundEffect("bullet_hit5");
64    public static readonly SoundEffect osuma1 = LoadSoundEffect("hit_1");
65
66    private Light valo = new Light();
67    #endregion
68
69    #region Kuvat
70
71    #region asekuvat
72    static readonly Image kranaatinKuva = LoadImage("Kranaatti_F1");
73    static readonly Image pistoolinMaaKuva = LoadImage("GLOCK18_maa");
74    static readonly Image rynkynMaaKuva = LoadImage("AK-74M_maa");
75    static readonly Image pumpparinMaaKuva = LoadImage("REMINGTON870_maa");
76    static readonly Image sawinMaaKuva = LoadImage("M249SAW_maa");
77    static readonly Image singonMaaKuva = LoadImage("RPG-7_maa");
78    static readonly Image snipanMaaKuva = LoadImage("SVDDRAGUNOV_maa");
79    static readonly Image kranaatinMaaKuva = LoadImage("F1FRAG_maa");
80    static readonly Image magnuminMaaKuva = LoadImage("Magnum_maa");
81    #endregion
82
83    #region kentänkuvat
84    // Kentän osat
85    static readonly Image valikonKuva = LoadImage("valikkotausta");
86    static readonly Image valikonPainikeKuva = LoadImage("menu_buttontest");
87    static GameObject menuGradient;
88    static readonly Image kivenKuva = LoadImage("kivi");
89    static readonly Image piikkilankaKuva = LoadImage("piikkilanka");
90    static readonly Image pystypiikkilankaKuva = LoadImage("piikkilankapysty");
91    static readonly Image vaakapuunKuva = LoadImage("puuvaaka");
92    static readonly Image naamioverkonKuva = LoadImage("naamioverkko");
93    static readonly Image pystypuunKuva = LoadImage("puupysty");
94    static readonly Image bussinkuva = LoadImage("bussi");
95    static readonly Image poistuvanseinänKuva = LoadImage("poistuvaseinä");
96    static readonly Image crack1 = LoadImage("crack1");
97    static readonly Image kiviRikki0 = LoadImage("kivirikki0");
98    static readonly Image kiviRikki1 = LoadImage("kivirikki1");
99    static readonly Image kiviRikki2 = LoadImage("kivirikki2");
100    static readonly Image kiviRikki3 = LoadImage("kivirikki3");
101    static readonly Image pystypuuRikki1 = LoadImage("puupystyrikki1");
102    static readonly Image pystypuuRikki2 = LoadImage("puupystyrikki2");
103    static readonly Image edustanKuva = LoadImage("edusta1");
104    static readonly Image seinäSoihdunKuva = LoadImage("seinäsoihtu");
105    static readonly Image valonKuva = LoadImage("valo1");
106    static readonly Image tynnyrinKuva = LoadImage("tynnyri");
107    static readonly Image killballPohja = LoadImage("killball_pohja");
108    static readonly Image killballKeski = LoadImage("killball_keski");
109    static readonly Image killballYla = LoadImage("killball_ylä");
110    static readonly Image helikopteriLaskeutumisAlusta = LoadImage("kopteri_laskeutumisalusta");
111    static readonly Image kuusi = LoadImage("kuusi");
112
113    static readonly Image hudKuva = LoadImage("hudtausta");
114    static readonly Image hudTäysi = LoadImage("hudtaustatäysi");
115    static readonly Image hudKuva2 = LoadImage("hudtausta2");
116    static readonly Image hudTäysi2 = LoadImage("hudtaustatäysi2");
117
118    static readonly Image laatikonKuva = LoadImage("kamaa");
119    static readonly Image laatikkoTyhjä = LoadImage("kamaatyhjä");
120    static readonly Image kamaaNäkymätön = LoadImage("kamaanäkymätön");
121    static readonly Image tyhjä = LoadImage("tyhjä");
122    static readonly Image[] laatikonAnimaatioKuvat = LoadImages("kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa", "kamaa1", "kamaa2", "kamaa3", "kamaa4");
123
124    static readonly Image zombinKuva = LoadImage("zombi");
125    static readonly Image[] zombinKuvat = LoadImages("zombi1", "zombi2", "zombi1", "zombi3");
126    static readonly Image korpinKuva = LoadImage("korppitesti");
127    #endregion
128
129    #region infinitekuvat
130    static readonly Image normaaliZombiKuva = LoadImage("zombi_tavallinen");
131    static readonly Image ampuvaZombiKuva = LoadImage("zombi_ak");
132    static readonly Image[] parasiittienKuvat = LoadImages("Parasiitti1", "Parasiitti2", "Parasiitti3");
133    static readonly Image[] parasiittienPartikkeliKuvat = LoadImages("paras_sirpale1", "paras_sirpale2", "paras_sirpale3", "paras_sirpale4", "paras_sirpale5");
134    #endregion
135
136    #endregion
137
138    #endregion
139
140    #region yleiset toiminnot
141
142    /// <summary>
143    /// Aloitetaan peli luomalla alkuvalikko.
144    /// </summary>
145    public override void Begin()
146    {
147        SoitaMusiikkia(0); // valikkotheme valikkoon
148        LuoAlkuValikko();
149    }
150
151    /// <summary>
152    /// Päivitetään pelaajiin liittyviä asioita.
153    /// </summary>
154    /// <param name="time">Aika pelin alusta ja edellisestä päivityksestä.</param>
155    protected override void Update(Time time)
156    {
157        base.Update(time);
158
159        // Päivitetään pelaajiin liittyviä juttuja.
160        for (int i = 0; i < pelaajat.Length; i++)
161        {
162            if (pelaajat[i] != null)
163            {
164                Vector suunta = (pelaajat[i].tahtain.Position - pelaajat[i].Position).Normalize();
165                pelaajat[i].Angle = suunta.Angle;
166
167                pelaajat[i].elamaPalkki.Position = new Vector(pelaajat[i].X, pelaajat[i].Y + 30);
168                pelaajat[i].infoRuutu.Position = new Vector(pelaajat[i].X, pelaajat[i].Y + 50);
169
170                // Tarkistetaan, ovatko pelaajat sallitun pelialueen ulkopuolella. Ei tarvita kentillä, joissa on piikkilangat reunoina.
171                if (OnkoSatunnaisKentta)
172                {
173                    if (pelaajat[i].Position.X > Vakiot.PELAAJAN_SUURIN_SALLITTU_X_KENTALLA || pelaajat[i].Position.Y > Vakiot.PELAAJAN_SUURIN_SALLITTU_Y_KENTALLA)
174                    {
175                        pelaajat[i].infoRuutu.Text = String.Format("Palaa taistelukentälle {0:0.00} sekunnin sisällä.", pelaajat[i].aikaPoissaKentalta.Value);
176                        if (pelaajat[i].OllaankoPoissaKentalta == false) pelaajat[i].PoistuttiinKentalta();
177                    }
178                    else if (pelaajat[i].Position.X < Vakiot.PELAAJAN_PIENIN_SALLITTU_X_KENTALLA || pelaajat[i].Position.Y < Vakiot.PELAAJAN_PIENIN_SALLITTU_Y_KENTALLA)
179                    {
180                        pelaajat[i].infoRuutu.Text = String.Format("Palaa taistelukentälle {0:0.00} sekunnin sisällä.", pelaajat[i].aikaPoissaKentalta.Value);
181                        if (pelaajat[i].OllaankoPoissaKentalta == false) pelaajat[i].PoistuttiinKentalta();
182                    }
183                    else
184                    {
185                        if (pelaajat[i].OllaankoPoissaKentalta == true)
186                        {
187                            pelaajat[i].infoRuutu.Text = "";
188                            pelaajat[i].PalattiinKentalle();
189                        }
190                    }
191                }
192            }
193        }
194
195        List<GameObject> fysiikkaolioita = GetObjects(x => x is PhysicsObject && !((PhysicsObject)x).IgnoresPhysicsLogics);
196        fysLaskuri.Text = fysiikkaolioita.Count.ToString();
197    }
198
199    Label fysLaskuri = new Label();
200
201
202    /// <summary>
203    /// Tehdään vahinkoa kohteelle.
204    /// </summary>
205    /// <param name="damagenKohde">Kohde, jota vahingoitetaan.</param>
206    /// <param name="damagenMäärä">Paljonko vahinkoa tehdään.</param>
207    void Damagea(Elava damagenKohde, double damagenMäärä)
208    {
209        damagenKohde.Elamat.Value -= damagenMäärä;
210        GameObject[] effects = Blood.AddNormalBlood(damagenKohde.Position, 3, 0.3);
211        foreach (GameObject blood in effects)
212        {
213            LisaaTehosteObjekti(blood);
214        }
215    }
216
217    /// <summary>
218    /// Tehdään vahinkoa kohteelle.
219    /// </summary>
220    /// <param name="damagenKohde">Kohde, jota vahingoitetaan.</param>
221    /// <param name="damagenMäärä">Paljonko vahinkoa tehdään.</param>
222    void Damagea(Tuhoutuva damagenKohde, double damagenMaara)
223    {
224        damagenKohde.Kesto.Value -= damagenMaara;
225    }
226
227    /// <summary>
228    /// Aloittaa pelin alusta ja palaa päävalikkoon. Poistaa kaiken tähän mennessä tehdyn.
229    /// </summary>
230    void PaaValikkoon()
231    {
232        ClearAll();
233        Camera.Reset();
234        Level.AmbientLight = 0.8;
235        SoitaMusiikkia(0); // valikkotheme valikkoon
236        LuoAlkuValikko(true);
237    }
238
239    /// <summary>
240    /// Kutsutaan, kun toinen pelaaja voittaa pelin.
241    /// </summary>
242    /// <param name="voittanutPelaaja">Pelaaja, joka voitti pelin.</param>
243    void Voitto(Pelaaja voittanutPelaaja)
244    {
245        // MediaPlayer.Play("EPIC VICTORY THEME SONG");
246        PimennaRuutua();
247        MultiSelectWindow voittoIkkuna = new MultiSelectWindow("Pelaaja " + voittanutPelaaja.Numero + " voitti pelin!\n\n" +
248            "Pelaajan 1 tapot: " + pelaajat[0].Tapot + "\n" +
249            "Pelaajan 2 tapot: " + pelaajat[1].Tapot, Color.White, "Päävalikkoon", "Lopeta peli");
250        voittoIkkuna.ItemSelected += delegate(int valinta)
251        {
252            switch (valinta)
253            {
254                case 0:
255                    PaaValikkoon();
256                    break;
257                case 1:
258                    Exit();
259                    break;
260            }
261        };
262        voittoIkkuna.Color = Color.Transparent;
263        voittoIkkuna.BorderColor = Color.Transparent;
264        voittoIkkuna.SelectionColor = Color.Green;
265        voittoIkkuna.DefaultCancel = 0;
266        voittoIkkuna.IsModal = true;
267        Add(voittoIkkuna);
268    }
269
270    /// <summary>
271    /// Kutsutaan, kun Infinite hävitään.
272    /// </summary>
273    /// <param name="havittyPeli">Peli, joka on hävitty.</param>
274    void InfiniteHavio(Infinite havittyPeli)
275    {
276        MediaPlayer.Play("ZombieGameOverFIX");
277        PimennaRuutua();
278        MultiSelectWindow havioIkkuna = new MultiSelectWindow("Peli päättyi!\nVihollisia tapettu " + havittyPeli.VihollisiaTapettu + " kpl.\nAikaa kului " + String.Format("{0:00}", havittyPeli.AikaPelinAlusta.CurrentTime) + " sekuntia.", Color.White, "Päävalikkoon", "Lopeta peli");
279        havioIkkuna.ItemSelected += delegate(int valinta)
280        {
281            switch (valinta)
282            {
283                case 0:
284                    PaaValikkoon();
285                    Infinite.OnkoPeliKaynnissa = false;
286                    break;
287                case 1:
288                    Infinite.OnkoPeliKaynnissa = false;
289                    Exit();
290                    break;
291            }
292        };
293        havioIkkuna.Color = Color.Transparent;
294        havioIkkuna.BorderColor = Color.Transparent;
295        havioIkkuna.SelectionColor = Color.Green;
296        havioIkkuna.DefaultCancel = 0;
297        havioIkkuna.IsModal = true;
298        Add(havioIkkuna);
299
300        havittyPeli.SpawnataankoVihollisia = false;
301
302        foreach (Pelaaja p in pelaajat)
303        {
304            if (p != null && p.Taskulamppu != null) p.Taskulamppu.Destroy();
305        }
306
307        foreach (Vihollinen vihu in havittyPeli.VihollisetKentalla)
308        {
309            vihu.Destroy();
310        }
311    }
312
313    /// <summary>
314    /// Tarkistetaan, onko piste näyttöruudun sisäpuolella.
315    /// </summary>
316    /// <param name="piste">Piste.</param>
317    /// <returns>Onko piste näytön alueella.</returns>
318    public bool OnkoNaytonAlueella(Vector piste)
319    {
320        Vector vasenYlakulma = Camera.ScreenToWorld(new Vector(Screen.Left, Screen.Top));
321        Vector oikeaYlaKulma = Camera.ScreenToWorld(new Vector(Screen.Right, Screen.Top));
322        Vector vasenAlaKulma = Camera.ScreenToWorld(new Vector(Screen.Left, Screen.Bottom));
323        //Vector oikeaAlaKulma = Camera.ScreenToWorld(new Vector(Screen.Right, Screen.Bottom));
324
325        if (piste.X > vasenYlakulma.X && piste.X < oikeaYlaKulma.X)
326            if (piste.Y < vasenYlakulma.Y && piste.Y > vasenAlaKulma.Y)
327                return true;
328        return false;
329    }
330
331    /// <summary>
332    /// Asettaa ikkunan koon halutuksi ja palaa päävalikkoon.
333    /// </summary>
334    /// <param name="leveys">Ikkunan leveys.</param>
335    /// <param name="korkeus">Ikkunan korkeus.</param>
336    void AsetaIkkunanKoko(int leveys, int korkeus)
337    {
338        SetWindowSize(leveys, korkeus);
339        PaaValikkoon();
340    }
341
342    /// <summary>
343    /// Poistetaan kentältä kaikki asiat, paitsi pelaajat.
344    /// </summary>
345    void RemoveAllEntities()
346    {
347        List<GameObject> pelioliot = GetObjects(x => x.Tag.ToString() != "pelaaja" && x.Tag.ToString() != "tahtain" && x.Tag.ToString() != "HUD");
348
349        foreach (GameObject olio in pelioliot)
350        {
351            olio.Destroy();
352        }
353        pelioliot.Clear();
354    }
355
356    /// <summary>
357    /// Pimennetään ruutua pikku hiljaa.
358    /// </summary>
359    void PimennaRuutua()
360    {
361        Timer ajastin = new Timer();
362        ajastin.Interval = 0.1;
363        ajastin.Timeout += delegate { Level.AmbientLight -= 0.01; };
364        ajastin.Start();
365    }
366
367    /// <summary>
368    /// Soitetaan musiikkia.
369    /// 0:Menu Background Theme
370    /// 1:Dark Lurk
371    /// 2:Zombin taustamusiikki
372    /// 3:OrcsCome
373    /// 4:OrcsCome Special
374    /// 5:MoozE-Radwind
375    /// </summary>
376    /// <param name="valinta">Mikä biisi soitetaan.</param>
377    void SoitaMusiikkia(int valinta)
378    {
379        MediaPlayer.IsRepeating = true;
380        switch (valinta)
381        {
382            case 0:
383                MediaPlayer.Play("Menu_BackGround");
384                break;
385            case 1:
386                MediaPlayer.Play("DarkLurk");
387                break;
388            case 2:
389                MediaPlayer.Play("zombi_taustamusa_1");
390                break;
391            case 3:
392                MediaPlayer.Play("OrcsCome");
393                break;
394            case 4:
395                MediaPlayer.Play("OrcsCome_special");
396                break;
397            case 5:
398                MediaPlayer.Play("03 MoozE - Radwind Pt1");
399                break;
400        }
401    }
402
403    /// <summary>
404    /// Piirretään valojuovia.
405    /// </summary>
406    /// <param name="position">Valojuovan tämänhetkinen sijainti.</param>
407    /// <param name="color">Valojuovan väri.</param>
408    /// <param name="lifetimeInSeconds">Kauanko valojuova pysyy kentällä.</param>
409    void DrawTracers(Vector position, Color color, double lifetimeInSeconds, double brightnessFactor)
410    {
411        color.AlphaComponent = (byte)(32 * brightnessFactor); // 64 toimii
412        GameObject tracer = new GameObject(2, 2);
413        tracer.Shape = Shape.Circle;
414        tracer.Color = color;
415        tracer.Position = position;
416        tracer.MaximumLifetime = TimeSpan.FromSeconds(lifetimeInSeconds);
417        Add(tracer);
418    }
419
420    /// <summary>
421    /// Piirretään valojuovia.
422    /// </summary>
423    /// <param name="tracingObject">Olio, josta valojuovat tulevat.</param>
424    /// <param name="color">Valojuovan väri.</param>
425    /// <param name="lifetimeInSeconds">Kauanko valojuova pysyy kentällä.</param>
426    /// <param name="brightnessFactor">Valojuovan kirkkaus.</param>
427    void DrawTracers(PhysicsObject tracingObject, Color color, double lifetimeInSeconds, double brightnessFactor)
428    {
429        color.AlphaComponent = (byte)(32 * brightnessFactor); // 64 toimii
430        GameObject tracer = new GameObject(60, 2);
431        tracer.Shape = Shape.Circle;
432        tracer.Color = color;
433        tracer.Position = tracingObject.Position;
434        tracer.Angle = tracingObject.Angle;
435        tracer.MaximumLifetime = TimeSpan.FromSeconds(lifetimeInSeconds);
436        Add(tracer);
437    }
438
439    public void LisaaTehosteObjekti(GameObject tehoste)
440    {
441        tehosteet.Add(tehoste);
442        if (tehosteet.Count > Vakiot.TEHOSTEOBJEKTIEN_MAX_MAARA)
443        {
444            tehosteet[0].Destroy();
445            tehosteet.RemoveAt(0);
446        }
447    }
448
449    #endregion
450
451    #region kenttä
452
453    /// <summary>
454    /// Luodaan kenttä ja kaikki siihen liittyvä, kuten pelaajat.
455    /// </summary>
456    /// <param name="kenttaTyyppi">Kentän luomistapa. 0: kenttä kuvasta, 1: satunnaisgeneroitu kenttä, 2: tyhjä kenttä.</param>
457    /// <param name="pelaajienMaara">Montako pelaajaa peliin tulee.</param>
458    void LuoKentta(int kenttaTyyppi, int pelaajienMaara, bool onkoInfinite)
459    {
460        Mouse.IsCursorVisible = false;
461        bool onkoSandbox = false;
462        AikaKentanAlusta.Reset();
463        AikaKentanAlusta.Start();
464        MessageDisplay.BackgroundColor = Color.Transparent;
465        MessageDisplay.TextColor = Color.White;
466        MessageDisplay.MessageTime = TimeSpan.FromSeconds(1.5);
467        Level.Size = new Vector(Vakiot.KENTAN_LEVEYS * Vakiot.KENTAN_RUUDUN_LEVEYS, Vakiot.KENTAN_KORKEUS * Vakiot.KENTAN_RUUDUN_KORKEUS);
468        Level.AmbientLight = 0.8;
469        Add(valo);
470        menuGradient.Destroy();
471        menuGradient = null;
472
473        Vector pelaajan1spawni = new Vector(-700.0, 0.0);
474        Vector pelaajan2spawni = new Vector(700.0, 0.0);
475        List<Vector> vaihtoehtoisetSpawnit = new List<Vector>();
476
477        switch (kenttaTyyppi)
478        {
479            case 0:
480                ColorTileMap ruudut = ColorTileMap.FromLevelAsset(ValittuKenttaTiedosto);
481                KentanOsat = new Kentta(ruudut.ColumnCount, ruudut.RowCount, "valekivi");
482
483                ruudut.SetTileMethod(Color.Black, LuoKentanOsa, piikkilankaKuva, "piikkilanka", 5);
484                ruudut.SetTileMethod(Color.Gray, LuoTuhoutuvaKentanOsa, kivenKuva, "kivi", 20, 1.0, 1.0);
485                ruudut.SetTileMethod(Color.DarkRed, LuoLapiMentavaKentanOsa, kivenKuva, "valekivi", 1.0, 1.0, 1);
486                ruudut.SetTileMethod(Color.Orange, LuoTuhoutuvaKentanOsa, pystypuunKuva, "puu", 10, 0.3, 1.0);
487                ruudut.SetTileMethod(Color.Red, LuoKentanOsa, pystypiikkilankaKuva, "piikkilanka", 5);
488                ruudut.SetTileMethod(Color.Brown, LuoTuhoutuvaKentanOsa, vaakapuunKuva, "puu", 10, 1.0, 0.3);
489                //ruudut.SetTileMethod(Color.ForestGreen, LuoLapiMentavaKentanOsa, naamioverkonKuva, "naamioverkko", 1);
490                ruudut.SetTileMethod(Color.Purple, LuoLaatikko);
491                ruudut.SetTileMethod(Color.Yellow, LuoLapiMentavaKentanOsa, seinäSoihdunKuva, "seinäsoihtu", 1.0, 1.0, -1);
492                ruudut.SetTileMethod(Color.Olive, LuoLapiMentavaKentanOsa, valonKuva, "valo", 6.0, 6.0, 1);
493                ruudut.SetTileMethod(Color.Rose, LuoTynnyri);
494                ruudut.SetTileMethod(Color.BloodRed, delegate(Vector p, double w, double h, IntPoint posInLevel)
495                {
496                    if (Infinite.CurrentGame != null)
497                        Infinite.CurrentGame.LisaaFixedSpawni(p);
498                });
499                ruudut.SetTileMethod(Color.BrightGreen, delegate(Vector p, double w, double h, IntPoint posInLevel)
500                {
501                    pelaajan1spawni = p;
502                });
503                ruudut.SetTileMethod(Color.Azure, delegate(Vector p, double w, double h, IntPoint posInLevel)
504                {
505                    pelaajan2spawni = p;
506                });
507                ruudut.SetTileMethod(Color.Gold, delegate(Vector p, double w, double h, IntPoint posInLevel)
508                {
509                    vaihtoehtoisetSpawnit.Add(p);
510                });
511                // ruudut.SetTileMethod(Color.YellowGreen, LuoLapiMentavaKentanOsa, helikopteriLaskeutumisAlusta, "laskeutumisalusta", 1.0, 1.0, -1);
512                ruudut.SetTileMethod(Color.YellowGreen, delegate(Vector p, double w, double h, IntPoint posInLevel) {
513                    LuoLapiMentavaKentanOsa(p, w, h, posInLevel, helikopteriLaskeutumisAlusta, "laskeutumisalusta", 1.0, 1.0, -1);
514                    if (Escape.Peli != null)
515                        Escape.Peli.LaskeutumisPaikka = p;
516                });
517                ruudut.SetTileMethod(Color.ForestGreen, LuoLapiMentavaKentanOsa, kuusi, "kuusi", 2.0, 2.0, 0);
518                ruudut.SetTileMethod(Color.DarkViolet, delegate(Vector p, double w, double h, IntPoint posInLevel) { Blood.AddNormalBlood(p, 5, 1.5); });
519
520                //ruudut.Optimize(Color.Gray);
521                ruudut.Execute(50, 50);
522                LuoPilvet((onkoInfinite && pelaajienMaara == 1));
523
524                break;
525            case 1:
526                string[] satunnaisKenttäTiedosto = LuoSatunnainenKenttäTiedosto(Vakiot.KENTAN_LEVEYS, Vakiot.KENTAN_KORKEUS);
527                TileMap satunnaisKenttä = TileMap.FromStringArray(satunnaisKenttäTiedosto);
528                satunnaisKenttä.SetTileMethod('1', LuoTuhoutuvaKentanOsa, kivenKuva, "kivi", 20, 1.0, 1.0);
529                satunnaisKenttä.Optimize();
530                satunnaisKenttä.Execute(Vakiot.KENTAN_RUUDUN_LEVEYS, Vakiot.KENTAN_RUUDUN_KORKEUS);
531
532                string[] pickupTiedosto = LuoSatunnainenPickupTiedosto(satunnaisKenttäTiedosto, Vakiot.PICKUPIEN_MAARA);
533                TileMap pickupit = TileMap.FromStringArray(pickupTiedosto);
534                pickupit.SetTileMethod('1', LuoKerattavaEsine);
535                pickupit.Execute(Vakiot.KENTAN_RUUDUN_LEVEYS, Vakiot.KENTAN_RUUDUN_KORKEUS);
536                LuoPilvet(false);
537                break;
538            case 2:
539                onkoSandbox = true;
540                break;
541        }
542
543        #region pelaajien spawnaus ja asettelu
544
545        bool kaytetaankoTaskuLamppua = false;
546
547        if (onkoInfinite)
548        {
549            if (pelaajienMaara == 1) kaytetaankoTaskuLamppua = true;
550        }
551
552        pelaajat[0] = LuoPelaaja(pelaajan1spawni, 43.5, 21.75, 1, Aseet.pelaaja1pistooliKuva, Color.Green, AsetustenKaytto.Asetukset.OnkoPelaajalla1Lasertahtainta, new Vector(Screen.Left + 130, Screen.Top - 70), kaytetaankoTaskuLamppua);
553        Add(pelaajat[0], 1);
554        pelaajat[0].SpawnausPaikat.AddRange(vaihtoehtoisetSpawnit);
555
556        AmmusMittari();
557        pelaajat[1] = LuoPelaaja(pelaajan2spawni, 43.5, 21.75, 2, Aseet.pelaaja2pistooliKuva, Color.Red, AsetustenKaytto.Asetukset.OnkoPelaajalla2Lasertahtainta, new Vector(Screen.Right - 130, Screen.Top - 70), kaytetaankoTaskuLamppua);
558        pelaajat[1].SpawnausPaikat.AddRange(vaihtoehtoisetSpawnit);
559
560
561        if (!onkoInfinite)
562        {
563            pelaajat[0].Voitti += Voitto;
564            pelaajat[0].Kuoli += delegate { pelaajat[1].Tapot.Value++; };
565            pelaajat[1].Voitti += Voitto;
566            pelaajat[1].Kuoli += delegate { pelaajat[0].Tapot.Value++; };
567        }
568
569        if (pelaajienMaara == 2)
570        {
571            Add(pelaajat[1], 1);
572            pelaajat[1].tahtain.Position = pelaajat[1].Position + new Vector(-200.0, 0.0);
573            Camera.Follow(pelaajat[0], pelaajat[1]);
574            AmmusMittari2();
575        }
576        else
577        {
578            Camera.Zoom(1);
579            Camera.Follow(pelaajat[0]);
580            pelaajat[1].elamaPalkki.IsVisible = false;
581            pelaajat[1].tahtain.IsVisible = false;
582            pelaajat[1].ValittuAseNaytto.IsVisible = false;
583            pelaajat[1].TappojenMaaraNaytto.IsVisible = false;
584        }
585
586        if (onkoSandbox) // laitetaan kaikki aseet, loputtomat ammukset ja loputtomat kranaatit
587        {
588            for (int i = 0; i < pelaajat.Length; i++)
589            {
590                pelaajat[i].LisaaAse(Aseet.LuoRynkky());
591                pelaajat[i].LisaaAse(Aseet.LuoMinigun());
592                pelaajat[i].LisaaAse(Aseet.LuoHaulikko());
593                pelaajat[i].LisaaAse(Aseet.LuoMagnum());
594                pelaajat[i].LisaaAse(Aseet.LuoSnipa());
595                pelaajat[i].LisaaAse(Aseet.LuoSinko());
596                pelaajat[i].LisaaAse(Aseet.LuoVarsijousi());
597                pelaajat[i].LisaaAse(Aseet.LuoOhjus());
598                pelaajat[i].LisaaAse(Aseet.LuoBinaryRifle());
599                pelaajat[i].LisaaAse(Aseet.LuoVintorez());
600                pelaajat[i].LisaaAse(Aseet.LuoAutomaattiHaulikko());
601
602                for (int j = 0; j < pelaajat[i].Aseet.Count; j++)
603                {
604                    pelaajat[i].Aseet[j].Ammo.MaxValue = Int32.MaxValue;
605                    pelaajat[i].Aseet[j].Ammo.Value = Int32.MaxValue;
606                    pelaajat[i].Aseet[j].MaxAmmo.MaxValue = Int32.MaxValue;
607                    pelaajat[i].Aseet[j].MaxAmmo.Value = Int32.MaxValue;
608
609                    pelaajat[i].KranaattienMaara = Int32.MaxValue;
610                }
611                ammusmittariNäyttö.IsVisible = false;
612                if (ammusmittariNäyttö2 != null)
613                    ammusmittariNäyttö2.IsVisible = false;
614            }
615        }
616        #endregion
617
618    }
619
620    /// <summary>
621    /// Luodaan kenttä onlinepelille.
622    /// </summary>
623    /// <param name="pelaajat">Pelaajat pelissä.</param>
624    /// <param name="kenttaTyyppi">Kentän tyyppi. 0: klassinen mäppi, 1: satunnaisgeneroitu mäppi, 2: tyhjä mäppi.</param>
625    void LuoOnlineKentta(List<Player> onlinePelaajat, int kenttaTyyppi)
626    {
627        Level.Background.Image = null;
628        Mouse.IsCursorVisible = false;
629        AikaKentanAlusta.Reset();
630        AikaKentanAlusta.Start();
631        MessageDisplay.BackgroundColor = Color.Transparent;
632        MessageDisplay.TextColor = Color.White;
633        MessageDisplay.MessageTime = TimeSpan.FromSeconds(1.5);
634        Level.Size = new Vector(Vakiot.KENTAN_LEVEYS * Vakiot.KENTAN_RUUDUN_LEVEYS, Vakiot.KENTAN_KORKEUS * Vakiot.KENTAN_RUUDUN_KORKEUS);
635        Level.AmbientLight = 0.8;
636        Add(valo);
637
638        foreach (Player pelaaja in onlinePelaajat)
639        {
640            Pelaaja p = new Pelaaja(43.5, 21.75, false, false);
641            p.Position = pelaaja.Position;
642            p.Angle = pelaaja.Angle;
643            p.Velocity = pelaaja.Velocity;
644            p.Elamat.Value = pelaaja.Health;
645            Add(p);
646            OnlineGame.PhysicalPlayers.Add(p);
647        }
648
649        pelaajat[0] = LuoPelaaja(new Vector(0.0, 0.0), 43.5, 21.75, 1, Aseet.pelaaja1pistooliKuva, Color.Green, AsetustenKaytto.Asetukset.OnkoPelaajalla1Lasertahtainta, new Vector(Screen.Left + 130, Screen.Top - 70), false); // false = onko taskulamppua
650        Add(pelaajat[0], 1);
651        AmmusMittari();
652        ClearControls();
653        AsetaOhjaimet();
654        SoitaMusiikkia(4); // OrcsCome Special nettipeliin
655    }
656
657    #region satunnaisgeneraatio
658
659    /// <summary>
660    /// Luodaan kentälle kerättävä esine.
661    /// </summary>
662    /// <param name="mikaLuodaan">Mikä esine luodaan, välillä 0..6.
663    /// (0:Pistooli, 1:Rynkky, 2:Haulikko, 3:Minigun, 4:Varsijousi, 5:Snipa, 6:Sinko, 7:Kranaatti)</param>
664    /// <param name="paikka">Paikka, johon esine luodaan.</param>
665    void LuoKerattavaEsine(Vector paikka, double leveys, double korkeus, IntPoint posInLevel)
666    {
667        int mikaLuodaan = RandomGen.NextIntWithProbabilities(0.20, 0.15, 0.10, 0.10, 0.10, 0.10, 0.05, 0.05, 0.15);
668        switch (mikaLuodaan)
669        {
670            // Pistooli
671            case 0:
672                Kerattava pistooli = LuoKerattava(paikka, Aseet.LuoPistooli(), pistoolinMaaKuva, 0.5);
673                pistooli.Kerattiin += JotainKerattiin;
674                Add(pistooli);
675                break;
676
677            // Rynkky
678            case 1:
679                Kerattava rynkky = LuoKerattava(paikka, Aseet.LuoRynkky(), rynkynMaaKuva);
680                rynkky.Kerattiin += JotainKerattiin;
681                Add(rynkky);
682                break;
683
684            // Haulikko
685            case 2:
686                Kerattava haulikko = LuoKerattava(paikka, Aseet.LuoHaulikko(), pumpparinMaaKuva);
687                haulikko.Kerattiin += JotainKerattiin;
688                Add(haulikko);
689                break;
690            case 3:
691                Kerattava magnum = LuoKerattava(paikka, Aseet.LuoMagnum(), magnuminMaaKuva);
692                magnum.Kerattiin += JotainKerattiin;
693                Add(magnum);
694                break;
695
696            // Minigun
697            case 4:
698                Kerattava minigun = LuoKerattava(paikka, Aseet.LuoMinigun(), sawinMaaKuva);
699                minigun.Kerattiin += JotainKerattiin;
700                Add(minigun);
701                break;
702
703            // Varsijousi
704            case 5:
705                /*Kerattava varsijousi = LuoKerattava(paikka, Aseet.LuoVarsijousi(), new Image(512, 512, Color.White));
706                varsijousi.Kerattiin += JotainKerattiin;
707                Add(varsijousi);*/
708                break;
709            // Snipa
710            case 6:
711                Kerattava snipa = LuoKerattava(paikka, Aseet.LuoSnipa(), snipanMaaKuva);
712                snipa.Kerattiin += JotainKerattiin;
713                Add(snipa);
714                break;
715
716            // Sinko
717            case 7:
718                Kerattava sinko = LuoKerattava(paikka, Aseet.LuoSinko(), singonMaaKuva);
719                sinko.Kerattiin += JotainKerattiin;
720                Add(sinko);
721                break;
722
723            case 8:
724                Kerattava kranaatti = LuoKerattava(paikka, 1, kranaatinMaaKuva, 0.8);
725                kranaatti.Kerattiin += JotainKerattiin;
726                Add(kranaatti);
727                break;
728            case 9:
729                /*Kerattava vintorez = LuoKerattava(paikka, Aseet.LuoVintorez(), vintorezMaaKuva);
730                vintorez.Kerattiin += JotainKerattiin;
731                Add(vintorez);*/
732                break;
733        }
734    }
735
736    /// <summary>
737    /// Luodaan kerättävä esine.
738    /// </summary>
739    /// <param name="paikka">Esineen paikka.</param>
740    /// <param name="mitaKerattiin">Mitä esineestä saa.</param>
741    /// <param name="kuva">Esineen kuva. Voi olla null.</param>
742    /// <param name="kuvanKoonMuutosKerroin">Paljonko kuvan kokoa muutetaan piirrettäessä. 1.0 ei tee mitään, suurempi kasvattaa ja pienempi pienentää.</param>
743    /// <returns>Esine.</returns>
744    Kerattava LuoKerattava(Vector paikka, object mitaKerattiin, Image kuva, double kuvanKoonMuutosKerroin = 1.0)
745    {
746        Kerattava k = new Kerattava(kuva.Width / 8 * kuvanKoonMuutosKerroin, kuva.Height / 8 * kuvanKoonMuutosKerroin, mitaKerattiin, paikka);
747        if (kuva != null)
748            k.Image = kuva;
749        return k;
750    }
751
752    /// <summary>
753    /// Kutsutaan, kun pelaaja törmää kerättävään esineeseen.
754    /// </summary>
755    /// <param name="p">Pelaaja, joka törmäsi.</param>
756    /// <param name="keratty">Se, mitä pelaaja sai kerättävästä esineestä.</param>
757    void JotainKerattiin(Pelaaja p, object keratty)
758    {
759        if (keratty is Ase)
760        {
761            Ase a = keratty as Ase;
762            if (!p.OnkoPelaajallaAse(a.Tag.ToString())) p.LisaaAse(a);
763            else
764            {
765                for (int i = 0; i < p.Aseet.Count; i++)
766                {
767                    if (p.Aseet[i].Tag.ToString() == a.Tag.ToString()) p.Aseet[i].MaxAmmo.Value += p.Aseet[i].Ammo.MaxValue; // jos pelaajalla on jo ase, annetaan aseeseen lippaallinen ammuksia
768                }
769            }
770        }
771        if (keratty is Int32)
772        {
773            p.KranaattienMaara++;
774        }
775    }
776
777    /// <summary>
778    /// Luodaan satunnainen String-taulukko nollista ja ykkösistä, jota voidaan käyttää kentän luontiin.
779    /// </summary>
780    /// <param name="leveys">Kentän leveys.</param>
781    /// <param name="korkeus">Kentän korkeus.</param>
782    /// <returns>Kenttä binäärimuodossa.</returns>
783    String[] LuoSatunnainenKenttäTiedosto(int leveys, int korkeus)
784    {
785        const int ARVOTTAVIA_SUKUPOLVIA = 2;
786        int[,] kentanArvot = new int[leveys, korkeus];
787        for (int i = 0; i < kentanArvot.GetLength(0); i++)
788        {
789            for (int j = 0; j < kentanArvot.GetLength(1); j++)
790            {
791                kentanArvot[i, j] = RandomGen.NextIntWithProbabilities(0.1);
792            }
793        }
794        int[,] kenttaLukuina = GameOfLife.ArvoSukupolvia(kentanArvot, leveys, korkeus, ARVOTTAVIA_SUKUPOLVIA);
795        String[] tulos = TaulukkoStringiksi(kenttaLukuina);
796        return tulos;
797    }
798
799    /// <summary>
800    /// Muunnetaan kaksiulotteinen int-taulukko string-taulukoksi.
801    /// </summary>
802    /// <param name="taulukko">Alkuperäinen int-taulukko.</param>
803    /// <returns>Int-taulukko string-taulukkona.</returns>
804    String[] TaulukkoStringiksi(int[,] taulukko)
805    {
806        String[] tulos = new String[taulukko.GetLength(1)];
807        for (int rivi = 0; rivi < taulukko.GetLength(0); rivi++)
808        {
809            for (int sarake = 0; sarake < taulukko.GetLength(1); sarake++)
810            {
811                tulos[rivi] += taulukko[rivi, sarake];
812            }
813        }
814        return tulos;
815    }
816
817    /// <summary>
818    /// Palauttaa string-lukutaulukon muunnettuna 2D-int-taulukoksi. Taulukon rivien pitää
819    /// olla samanpituisia.
820    /// </summary>
821    /// <param name="taulukko">Muunnettava taulukko.</param>
822    /// <returns>Taulukko int-muodossa.<returns>
823    int[,] TaulukkoIntiksi(String[] taulukko)
824    {
825        int[,] tulos = new int[taulukko.Length, taulukko[0].Length];
826        for (int rivi = 0; rivi < taulukko.Length; rivi++)
827        {
828            for (int sarake = 0; sarake < taulukko[0].Length; sarake++)
829            {
830                tulos[rivi, sarake] = int.Parse(taulukko[rivi][sarake].ToString());
831            }
832        }
833        return tulos;
834    }
835
836    /// <summary>
837    /// Muuntaa int-taulukon bool-taulukoksi. Luvusta 0 tulee true, muista false.
838    /// </summary>
839    /// <param name="taulukkoIntina">Muunnettava taulukko.</param>
840    /// <returns>Taulukko boolina.</returns>
841    bool[,] TaulukkoBooliksi(int[,] taulukkoIntina)
842    {
843        bool[,] tulos = new bool[taulukkoIntina.GetLength(0), taulukkoIntina.GetLength(1)];
844        for (int i = 0; i < taulukkoIntina.GetLength(0); i++)
845        {
846            for (int j = 0; j < taulukkoIntina.GetLength(1); j++)
847            {
848                if (taulukkoIntina[i, j] == 0) tulos[i, j] = true;
849                else tulos[i, j] = false;
850            }
851        }
852        return tulos;
853    }
854
855    /// <summary>
856    /// Palauttaa int-taulukon, jonka alkioiden arvot voivat olla VAIN 0 tai 1 käännettynä siten, että alkioiden
857    /// arvot ovat päinvastaiset.
858    /// </summary>
859    /// <param name="taulukko">Käännettävä taulukko.</param>
860    /// <returns>Käännetty taulukko.</returns>
861    int[,] KaannaTaulukko(int[,] taulukko)
862    {
863        for (int i = 0; i < taulukko.GetLength(0); i++)
864        {
865            for (int j = 0; j < taulukko.GetLength(1); j++)
866            {
867                if (taulukko[i, j] == 0) taulukko[i, j] = 1;
868                else taulukko[i, j] = 0;
869            }
870        }
871        return taulukko;
872    }
873
874    /// <summary>
875    /// Palauttaa niiden taulukon alkioiden indeksit, joissa on etsittävä luku.
876    /// </summary>
877    /// <param name="taulukko">Taulukko, josta lukua etsitään.</param>
878    /// <param name="mitäEtsitään">Mitä lukua etsitään.</param>
879    /// <returns>Indeksit vektorilistana.</returns>
880    List<Vector> TaulukonAlkioidenIndeksit(int[,] taulukko, int mitäEtsitään)
881    {
882        List<Vector> indeksit = new List<Vector>();
883        for (int i = 0; i < taulukko.GetLength(0); i++)
884        {
885            for (int j = 0; j < taulukko.GetLength(1); j++)
886            {
887                if (taulukko[i, j] == mitäEtsitään) indeksit.Add(new Vector(i, j));
888            }
889        }
890        return indeksit;
891    }
892
893    /// <summary>
894    /// Luodaan tiedosto pickupien luontia varten siten, ettei pickupeja mene seinien päälle.
895    /// </summary>
896    /// <param name="kentanKiinteatOsat">Kentän seinät.</param>
897    /// <returns>String-taulukko, jossa on pickupien paikat.</returns>
898    String[] LuoSatunnainenPickupTiedosto(String[] kentanKiinteatOsat, int pickupienMaara)
899    {
900        int[,] pickupienPaikat = new int[kentanKiinteatOsat.Length, kentanKiinteatOsat[0].Length];
901
902        // Ne paikat, jotka ovat tyhjiä kenttägeneraation jäljiltä.
903        int[,] pickupienMahdollisetPaikat = TaulukkoIntiksi(kentanKiinteatOsat);
904        pickupienMahdollisetPaikat = KaannaTaulukko(pickupienMahdollisetPaikat);
905        List<Vector> indeksitJoissaOnTyhjää = TaulukonAlkioidenIndeksit(pickupienMahdollisetPaikat, 1);
906
907        for (int i = 0; i < pickupienMaara; i++)
908        {
909            Vector paikka = RandomGen.SelectOne<Vector>(indeksitJoissaOnTyhjää);
910            int x = (int)paikka.X;
911            int y = (int)paikka.Y;
912            pickupienPaikat[x, y] = 1;
913        }
914        String[] pickupienPaikatStringinä = TaulukkoStringiksi(pickupienPaikat);
915        return pickupienPaikatStringinä;
916    }
917    #endregion
918
919    #region kentän osat
920
921    /// <summary>
922    /// Luo staattisen kentän osan, joka voi tuhoutua.
923    /// </summary>
924    /// <param name="paikka">Kappaleen paikka.</param>
925    /// <param name="leveys">Kappaleen leveys.</param>
926    /// <param name="korkeus">Kappaleen korkeus.</param>
927    /// <param name="kuva">Kappaleen kuva.</param>
928    /// <param name="tag">Kappaleen tagi.</param>
929    /// <param name="kesto">Kappaleen kesto.</param>
930    public void LuoTuhoutuvaKentanOsa(Vector paikka, double leveys, double korkeus, IntPoint positionInLevelArray, Image kuva, string tag, int kesto, double leveydenKerroin, double korkeudenKerroin)
931    {
932        Tuhoutuva kentanosa = new Tuhoutuva(leveys * leveydenKerroin, korkeus * korkeudenKerroin, kesto);
933        kentanosa.Position = paikka;
934        kentanosa.MakeStatic();
935        kentanosa.Image = kuva;
936        kentanosa.Tag = tag;
937        kentanosa.CollisionIgnoreGroup = 1;
938        kentanosa.PositionInLevelArray = positionInLevelArray;
939        kentanosa.Kesto.LowerLimit += delegate
940        {
941            if (KentanOsat != null)
942                KentanOsat.TuhoaSeina(kentanosa.PositionInLevelArray.X, kentanosa.PositionInLevelArray.Y);
943            kentanosa.Destroy();
944        };
945        Add(kentanosa);
946
947        if (KentanOsat != null)
948            KentanOsat.LisaaSeina(positionInLevelArray.X, positionInLevelArray.Y, kentanosa);
949    }
950
951    /// <summary>
952    /// Luo staattisen kentän osan, joka ei voi tuhoutua.
953    /// </summary>
954    /// <param name="paikka">Kappaleen paikka.</param>
955    /// <param name="leveys">Kappaleen leveys.</param>
956    /// <param name="korkeus">Kappaleen korkeus.</param>
957    /// <param name="kuva">Kappaleen kuva.</param>
958    /// <param name="tag">Kappaleen tagi.</param>
959    /// <param name="collisionIgnoreGroup">Kappaleen törmäysryhmä.</param>
960    void LuoKentanOsa(Vector paikka, double leveys, double korkeus, IntPoint positionInLevelArray, Image kuva, string tag, int collisionIgnoreGroup)
961    {
962        PhysicsObject kentanosa = new PhysicsObject(leveys, korkeus);
963        kentanosa.Position = paikka;
964        kentanosa.MakeStatic();
965        kentanosa.Image = kuva;
966        kentanosa.Tag = tag;
967        kentanosa.CollisionIgnoreGroup = collisionIgnoreGroup;
968        kentanosa.PositionInLevelArray = positionInLevelArray;
969        Add(kentanosa);
970
971        KentanOsat.LisaaSeina(positionInLevelArray.X, positionInLevelArray.Y, kentanosa);
972    }
973
974    /// <summary>
975    /// Luo liikkumattoman kentän osan, johon ei voi törmätä.
976    /// </summary>
977    /// <param name="paikka">Kappaleen paikka.</param>
978    /// <param name="leveys">Kappaleen leveys.</param>
979    /// <param name="korkeus">Kappaleen korkeus.</param>
980    /// <param name="kuva">Kappaleen kuva.</param>
981    /// <param name="tag">Kappaleen tagi.</param>
982    void LuoLapiMentavaKentanOsa(Vector paikka, double leveys, double korkeus, IntPoint positionInLevelArray, Image kuva, string tag, double leveydenKerroin, double korkeudenKerroin, int layer = -1)
983    {
984        GameObject kentanosa = new GameObject(leveys * leveydenKerroin, korkeus * korkeudenKerroin);
985        kentanosa.Image = kuva;
986        kentanosa.Tag = tag;
987        kentanosa.Position = paikka;
988        kentanosa.PositionInLevelArray = positionInLevelArray;
989        Add(kentanosa, layer);
990
991        KentanOsat.LisaaSeina(positionInLevelArray.X, positionInLevelArray.Y, kentanosa);
992    }
993
994    /// <summary>
995    /// Luodaan liikkuva kentän osa.
996    /// </summary>
997    /// <param name="paikka">Paikka.</param>
998    /// <param name="leveys">Leveys.</param>
999    /// <param name="korkeus">Korkeus.</param>
1000    /// <param name="kuva">Kuva.</param>
1001    /// <param name="tag">Tagi.</param>
1002    /// <param name="shape">Muoto.</param>
1003    /// <returns>Kentän osa.</returns>
1004    PhysicsObject LuoLiikkuvaKentanOsa(Vector paikka, double leveys, double korkeus, Image kuva, string tag, Shape shape)
1005    {
1006        PhysicsObject kentanosa = new PhysicsObject(leveys, korkeus);
1007        kentanosa.Position = paikka;
1008        kentanosa.Tag = tag;
1009        if (kuva != null) kentanosa.Image = kuva;
1010        kentanosa.Shape = shape;
1011        Add(kentanosa);
1012        return kentanosa;
1013    }
1014
1015    /// <summary>
1016    /// Luodaan räjähtävä tynnyri.
1017    /// </summary>
1018    /// <param name="paikka">Tynnyrin paikka.</param>
1019    /// <param name="leveys">Tynnyrin leveys.</param>
1020    /// <param name="korkeus">Tynnyrin korkeus.</param>
1021    void LuoTynnyri(Vector paikka, double leveys, double korkeus, IntPoint posInLevel)
1022    {
1023        Tuhoutuva tynnyri = new Tuhoutuva(leveys / 1.5, korkeus / 1.5, 1);
1024        tynnyri.Image = tynnyrinKuva;
1025        tynnyri.Position = paikka;
1026        tynnyri.Shape = Shape.Circle;
1027        tynnyri.Mass = 600;
1028        tynnyri.LinearDamping = 0.90;
1029        tynnyri.AngularDamping = 0.90;
1030        tynnyri.Angle = RandomGen.NextAngle();
1031        tynnyri.Kesto.LowerLimit += delegate
1032        {
1033            Partikkelit.AddExplosionEffect(tynnyri.Position, 600);
1034            //Flame f = Partikkelit.CreateFlames(tynnyri.Position, 30);
1035            //Add(f);
1036
1037            Explosion rajahdys = new Explosion(200);
1038            rajahdys.Position = tynnyri.Position;
1039            rajahdys.Image = tyhjä;
1040            rajahdys.Sound = Aseet.singonAani;
1041            rajahdys.Force = 400;
1042            rajahdys.Speed = 1000;
1043            rajahdys.ShockwaveColor = Color.Black;
1044            rajahdys.ShockwaveReachesObject += delegate(IPhysicsObject paineaallonKohde, Vector shokki) { RajahdysOsuu(paineaallonKohde, shokki, tynnyri.Position, Aseet.SINGON_MAKSIMI_DAMAGE); };
1045            Add(rajahdys);
1046            tynnyri.Destroy();
1047        };
1048        Add(tynnyri);
1049        //tynnyri.Hit(RandomGen.NextVector(100.0, 1000.0));
1050    }
1051
1052    /// <summary>
1053    /// Luodaan kentän päälle pilviä, jotka liikkuvat hiljalleen.
1054    /// </summary>
1055    void LuoPilvet(bool onkoInfinite)
1056    {
1057        GameObject pilvet = new GameObject(8192, 8192);
1058        if (onkoInfinite) pilvet.Image = LoadImage("himmeatpilvet");
1059        else pilvet.Image = LoadImage("pilvet2");
1060        pilvet.Tag = "pilvet";
1061        Add(pilvet, 2);
1062        Layers[2].RelativeTransition = new Vector(2.0, 2.0);
1063        RandomMoverBrain rb = new RandomMoverBrain(0.3);
1064        pilvet.Brain = rb;
1065        rb.WanderRadius = 1000;
1066        rb.ChangeMovementSeconds = 10.0;
1067        rb.TurnWhileMoving = false;
1068    }
1069
1070    /// <summary>
1071    /// Luodaan laatikko, josta voi kerätä kamaa.
1072    /// </summary>
1073    /// <param name="paikka">Laatikon paikka.</param>
1074    /// <param name="leveys">Laatikon leveys.</param>
1075    /// <param name="korkeus">Laatikon korkeus.</param>
1076    void LuoLaatikko(Vector paikka, double leveys, double korkeus, IntPoint posInLevel)
1077    {
1078        Laatikko laatikko = new Laatikko(leveys, korkeus);
1079        laatikko.Animation = new Animation(laatikonAnimaatioKuvat);
1080        laatikko.Animation.Start();
1081        laatikko.MakeStatic();
1082        laatikko.Animation.FPS = 10;
1083        laatikko.Position = paikka;
1084        laatikko.Tag = "laatikko";
1085        AddCollisionHandler(laatikko, AnnaKamaa);
1086        Add(laatikko);
1087    }
1088
1089    void LuoKillBall(Vector paikka)
1090    {
1091        PhysicsObject killball = LuoLiikkuvaKentanOsa(paikka, 200.0, 200.0, killballPohja, "killball", Shape.Circle);
1092        killball.AngularDamping = 1.0;
1093        killball.AngularVelocity = 5.0;
1094
1095        PhysicsObject killballKeskiOsa = new PhysicsObject(200.0, 200.0);
1096        killballKeskiOsa.Image = killballKeski;
1097        killballKeskiOsa.MakeStatic();
1098        killballKeskiOsa.Shape = Shape.Circle;
1099        killballKeskiOsa.AngularDamping = 1.0;
1100        killballKeskiOsa.AngularVelocity = -6.0;
1101        killball.Add(killballKeskiOsa);
1102
1103        PhysicsObject killballYlaOsa = new PhysicsObject(200.0, 200.0);
1104        killballYlaOsa.Image = killballYla;
1105        killballYlaOsa.MakeStatic();
1106        killballYlaOsa.Shape = Shape.Circle;
1107        killballYlaOsa.AngularDamping = 1.0;
1108        killballYlaOsa.AngularVelocity = 8.0;
1109        killballKeskiOsa.Add(killballYlaOsa);
1110
1111        AddCollisionHandler<PhysicsObject, Pelaaja>(
1112            killball, delegate(PhysicsObject kb, Pelaaja pelaaja)
1113        {
1114            Damagea(pelaaja, 20);
1115            PlaySound("KillBall_Kill");
1116        });
1117    }
1118
1119    void LuoHelikopteri(Vector paikka)
1120    {
1121        Helikopteri kopteri = new Helikopteri(330, 73, 50, false); // 211, 171
1122        kopteri.Position = paikka;
1123        Add(kopteri, 2);
1124
1125#if DEBUG
1126        Vector[] reitti = { new Vector(200.0, 200.0), new Vector(100.0, -500.0), new Vector(0.0, -100.0) };
1127        Keyboard.Listen(Key.I, ButtonState.Pressed, kopteri.NouseIlmaan, null);
1128        Keyboard.Listen(Key.U, ButtonState.Pressed, kopteri.Laskeudu, null);
1129        Keyboard.Listen(Key.Y, ButtonState.Pressed, delegate { kopteri.LiikutaKopteria(100.0, true, reitti); }, null);
1130#endif
1131    }
1132
1133    /// <summary>
1134    /// Asetetaan pelaajan lisäämät seinät siten, että se eivät mene sisäkkäin.
1135    /// </summary>
1136    /// <param name="realPos">Paikka, johon seinää yritetään lisätä.</param>
1137    Vector SijoitaKentanosaRuudukkoon(Vector mousePos)
1138    {
1139        int merkki = Math.Sign(mousePos.X);
1140        double x = mousePos.X - mousePos.X % Vakiot.KENTAN_RUUDUN_LEVEYS + merkki * Vakiot.KENTAN_RUUDUN_LEVEYS / 2;
1141        merkki = Math.Sign(mousePos.Y);
1142        double y = mousePos.Y - (mousePos.Y % Vakiot.KENTAN_RUUDUN_KORKEUS) + merkki * Vakiot.KENTAN_RUUDUN_KORKEUS / 2;
1143
1144        Vector posRuudukossa = new Vector(x, y);
1145        return posRuudukossa;
1146    }
1147
1148    #endregion
1149
1150    #endregion
1151
1152    #region valikot
1153    /// <summary>
1154    /// Luodaan pelille alkuvalikko.
1155    /// </summary>
1156    /// <param name="isEverythingCleared">Jos kutsutaan ClearAllin jälkeen.</param>
1157    void LuoAlkuValikko(bool isEverythingCleared = false)
1158    {
1159        MW2_My_Warfare_2_.Peli = this;
1160        AsetustenKaytto.LataaAsetukset();
1161        Infinite.OnkoPeliKaynnissa = false;
1162        AnimatedMultiSelectWindow valikko = new AnimatedMultiSelectWindow("MY WARFARE 2", valikonPainikeKuva,
1163        "Uusi peli", "Multiplayer", "Asetukset", "Lopeta peli");
1164        valikko.ItemSelected += PainettiinAlkuValikonNappia;
1165        valikko.Color = Color.Transparent;
1166        valikko.BorderColor = Color.Transparent;
1167        valikko.MovementSpeed = 450;
1168        Level.Background.Image = valikonKuva;
1169        Level.BackgroundColor = Color.Black;
1170        Level.AmbientLight = 1.0;
1171        valikko.DefaultCancel = 4;
1172        Partikkelit.LisaaValikkoTaustaPartikkelit();
1173        Add(valikko);
1174
1175        if (menuGradient == null || menuGradient.IsDestroyed || !menuGradient.IsAddedToGame || isEverythingCleared) // jos null tai poistettu pelistä tai jos tullaan ClearAllin kautta
1176        {
1177            menuGradient = new GameObject(1920, 1080);
1178            menuGradient.Image = LoadImage("menu_gradient");
1179            Add(menuGradient);
1180        }
1181    }
1182
1183    /// <summary>
1184    /// Alkuvalikon nappien painalluksen käsittely.
1185    /// </summary>
1186    /// <param name="valinta">Painettu nappi.</param>
1187    void PainettiinAlkuValikonNappia(int valinta)
1188    {
1189        switch (valinta)
1190        {
1191            case 0:
1192                LuoPelimuodonValintaValikko();
1193                break;
1194            case 1:
1195                LuoOnlineValikko();
1196                break;
1197            case 2:
1198                LuoAsetusIkkuna();
1199                break;
1200            case 3:
1201                Exit();
1202                break;
1203        }
1204    }
1205
1206    void LuoOnlineValikko()
1207    {
1208        AnimatedMultiSelectWindow onlineValikko = new AnimatedMultiSelectWindow("Valitse pelimuoto", valikonPainikeKuva, "Liity peliin", "Syötä IP", "Syötä portti", "Syötä salasana", "Takaisin");
1209        onlineValikko.ItemSelected += PainettiinOnlineValikonNappia;
1210        onlineValikko.Color = Color.Transparent;
1211        onlineValikko.BorderColor = Color.Transparent;
1212        Level.Background.Image = valikonKuva;
1213        Level.BackgroundColor = Color.Black;
1214        onlineValikko.DefaultCancel = 2;
1215        //onlineValikko.Position = new Vector(0, Screen.Top - 100);
1216        Add(onlineValikko);
1217
1218    }
1219
1220    void PainettiinOnlineValikonNappia(int valinta)
1221    {
1222        switch (valinta)
1223        {
1224            case 0:
1225                OnlineGame.JoinGame(new System.Net.IPEndPoint(System.Net.IPAddress.Parse(OnlineGame.ServerIP.ToString()), OnlineGame.ServerPort));
1226                LuoOnlineKentta(OnlineGame.CurrentGame.ConnectedPlayers, 2);
1227
1228                break;
1229            case 1:
1230                InputWindow ipIkkuna = new InputWindow("Syötä serverin IP:");
1231                ipIkkuna.Color = Color.Transparent;
1232                ipIkkuna.InputBox.BorderColor = Color.Green;
1233                ipIkkuna.InputBox.Cursor.Color = Color.Green;
1234                ipIkkuna.MaxCharacters = 15;
1235                ipIkkuna.OKButton.Clicked += delegate
1236                {
1237                    OnlineGame.ServerIP.Clear();
1238                    OnlineGame.ServerIP.Append(ipIkkuna.InputBox.Text);
1239                    LuoOnlineValikko();
1240                };
1241                Add(ipIkkuna);
1242                break;
1243            case 2:
1244                InputWindow porttiIkkuna = new InputWindow("Syötä serverin portti:");
1245                porttiIkkuna.Color = Color.Transparent;
1246                porttiIkkuna.InputBox.BorderColor = Color.Green;
1247                porttiIkkuna.InputBox.Cursor.Color = Color.Green;
1248                porttiIkkuna.MaxCharacters = 5;
1249                porttiIkkuna.OKButton.Clicked += delegate
1250                {
1251                    OnlineGame.ServerPort = int.Parse(porttiIkkuna.InputBox.Text);
1252                    LuoOnlineValikko();
1253                };
1254                Add(porttiIkkuna);
1255
1256                break;
1257            case 3:
1258                InputWindow salasanaIkkuna = new InputWindow("Syötä serverin portti:");
1259                salasanaIkkuna.Color = Color.Transparent;
1260                salasanaIkkuna.InputBox.BorderColor = Color.Green;
1261                salasanaIkkuna.InputBox.Cursor.Color = Color.Green;
1262                salasanaIkkuna.OKButton.Clicked += delegate
1263                {
1264                    OnlineGame.ServerPassword.Clear();
1265                    OnlineGame.ServerPassword.Append(salasanaIkkuna.InputBox.Text);
1266                    LuoOnlineValikko();
1267                };
1268                Add(salasanaIkkuna);
1269                break;
1270            case 4:
1271                LuoAlkuValikko();
1272                break;
1273        }
1274    }
1275
1276    /// <summary>
1277    /// Asetukset, kuten fullscreen-valinta, antialiasing ja resoluutio.
1278    /// </summary>
1279    void LuoAsetusIkkuna()
1280    {
1281        AsetustenKaytto.LataaAsetukset();
1282        Mouse.IsCursorVisible = true;
1283        MultiSelectWindow paluu = new MultiSelectWindow("Asetukset", "Tallenna ja palaa päävalikkoon", "Palauta oletusasetukset");
1284        paluu.ItemSelected += delegate(int valinta)
1285        {
1286            switch (valinta)
1287            {
1288                case 0:
1289                    AsetustenKaytto.TallennaAsetukset();
1290                    PaaValikkoon();
1291                    break;
1292                case 1:
1293                    AsetustenKaytto.PalautaOletusAsetukset();
1294                    AsetustenKaytto.TallennaAsetukset();
1295                    PaaValikkoon();
1296                    break;
1297            }
1298        };
1299        paluu.Color = Color.Transparent;
1300        paluu.BorderColor = Color.Transparent;
1301        paluu.SelectionColor = Color.Green;
1302        Level.Background.Image = valikonKuva;
1303        Level.BackgroundColor = Color.Black;
1304        paluu.DefaultCancel = 0;
1305        paluu.Position = new Vector(0, Screen.Top - 100);
1306        Add(paluu);
1307
1308        OnOffButton fullscreenNappi = new OnOffButton(20, 20, AsetustenKaytto.Asetukset.OnkoFullscreen);
1309        fullscreenNappi.Position = new Vector(0.0, paluu.Y - 100);
1310        Add(fullscreenNappi);
1311        fullscreenNappi.Clicked += delegate { AsetustenKaytto.Asetukset.OnkoFullscreen = fullscreenNappi.IsPressed; this.IsFullScreen = AsetustenKaytto.Asetukset.OnkoFullscreen; };
1312
1313        Label fullscreenTeksti = new Label("Fullscreen:");
1314        fullscreenTeksti.Position = new Vector(fullscreenNappi.X - 100, fullscreenNappi.Y);
1315        Add(fullscreenTeksti);
1316
1317        OnOffButton antialiasingNappi = new OnOffButton(20, 20, AsetustenKaytto.Asetukset.OnkoAntialiasing);
1318        antialiasingNappi.Position = new Vector(0.0, fullscreenNappi.Y - 50);
1319        Add(antialiasingNappi);
1320        antialiasingNappi.Clicked += delegate { AsetustenKaytto.Asetukset.OnkoAntialiasing = antialiasingNappi.IsPressed; Game.SmoothTextures = AsetustenKaytto.Asetukset.OnkoAntialiasing; };
1321
1322        Label antialiasingTeksti = new Label("Antialiasing:");
1323        antialiasingTeksti.Position = new Vector(antialiasingNappi.X - 100, antialiasingNappi.Y);
1324        Add(antialiasingTeksti);
1325
1326        Label resoluutiotOtsikko = new Label("Resoluutio:");
1327        resoluutiotOtsikko.Position = new Vector(antialiasingTeksti.X, antialiasingTeksti.Y - 50);
1328        Add(resoluutiotOtsikko);
1329
1330        PushButton resoluutio800x600 = new PushButton(20, 20);
1331        resoluutio800x600.Position = new Vector(100.0, resoluutiotOtsikko.Y - 50);
1332        Add(resoluutio800x600);
1333        resoluutio800x600.Clicked += delegate { AsetaIkkunanKoko(800, 600); };
1334
1335        Label resoluutio800x600Teksti = new Label("800 x 600");
1336        resoluutio800x600Teksti.Position = new Vector(resoluutio800x600.X - 100, resoluutio800x600.Y);
1337        Add(resoluutio800x600Teksti);
1338
1339        PushButton resoluutio1024x768 = new PushButton(20, 20);
1340        resoluutio1024x768.Position = new Vector(100.0, resoluutio800x600.Y - 50);
1341        Add(resoluutio1024x768);
1342        resoluutio1024x768.Clicked += delegate { AsetaIkkunanKoko(1024, 768); };
1343
1344        Label resoluutio1024x768Teksti = new Label("1024 x 768");
1345        resoluutio1024x768Teksti.Position = new Vector(resoluutio1024x768.X - 100, resoluutio1024x768.Y);
1346        Add(resoluutio1024x768Teksti);
1347
1348        PushButton resoluutio1280x1024 = new PushButton(20, 20);
1349        resoluutio1280x1024.Position = new Vector(100.0, resoluutio1024x768.Y - 50);
1350        Add(resoluutio1280x1024);
1351        resoluutio1280x1024.Clicked += delegate { AsetaIkkunanKoko(1280, 1024); };
1352
1353        Label resoluutio1280x1024Teksti = new Label("1280 x 1024");
1354        resoluutio1280x1024Teksti.Position = new Vector(resoluutio1280x1024.X - 100, resoluutio1280x1024.Y);
1355        Add(resoluutio1280x1024Teksti);
1356
1357        PushButton resoluutio1600x1200 = new PushButton(20, 20);
1358        resoluutio1600x1200.Position = new Vector(100.0, resoluutio1280x1024.Y - 50);
1359        Add(resoluutio1600x1200);
1360        resoluutio1600x1200.Clicked += delegate { AsetaIkkunanKoko(1600, 1200); };
1361
1362        Label resoluutio1600x1200Teksti = new Label("1600 x 1200");
1363        resoluutio1600x1200Teksti.Position = new Vector(resoluutio1600x1200.X - 100, resoluutio1600x1200.Y);
1364        Add(resoluutio1600x1200Teksti);
1365
1366        PushButton resoluutio1920x1080 = new PushButton(20, 20);
1367        resoluutio1920x1080.Position = new Vector(100.0, resoluutio1600x1200.Y - 50);
1368        Add(resoluutio1920x1080);
1369        resoluutio1920x1080.Clicked += delegate { AsetaIkkunanKoko(1920, 1080); };
1370
1371        Label resoluutio1920x1080Teksti = new Label("1920 x 1080");
1372        resoluutio1920x1080Teksti.Position = new Vector(resoluutio1920x1080.X - 100, resoluutio1920x1080.Y);
1373        Add(resoluutio1920x1080Teksti);
1374
1375        OnOffButton pelaaja1LaserNappi = new OnOffButton(20, 20, AsetustenKaytto.Asetukset.OnkoPelaajalla1Lasertahtainta);
1376        pelaaja1LaserNappi.Position = new Vector(0.0, resoluutio1920x1080.Y - 50);
1377        Add(pelaaja1LaserNappi);
1378        pelaaja1LaserNappi.Clicked += delegate { AsetustenKaytto.Asetukset.OnkoPelaajalla1Lasertahtainta = !AsetustenKaytto.Asetukset.OnkoPelaajalla1Lasertahtainta; };
1379
1380        Label pelaaja1LaserTeksti = new Label("Pelaajan 1 lasertähtäin:");
1381        pelaaja1LaserTeksti.Position = new Vector(pelaaja1LaserNappi.X - 150, pelaaja1LaserNappi.Y);
1382        Add(pelaaja1LaserTeksti);
1383
1384        OnOffButton pelaaja2LaserNappi = new OnOffButton(20, 20, AsetustenKaytto.Asetukset.OnkoPelaajalla2Lasertahtainta);
1385        pelaaja2LaserNappi.Position = new Vector(0.0, pelaaja1LaserNappi.Y - 50);
1386        Add(pelaaja2LaserNappi);
1387        pelaaja2LaserNappi.Clicked += delegate { AsetustenKaytto.Asetukset.OnkoPelaajalla2Lasertahtainta = !AsetustenKaytto.Asetukset.OnkoPelaajalla2Lasertahtainta; };
1388
1389        Label pelaaja2LaserTeksti = new Label("Pelaajan 2 lasertähtäin:");
1390        pelaaja2LaserTeksti.Position = new Vector(pelaaja2LaserNappi.X - 150, pelaaja2LaserNappi.Y);
1391        Add(pelaaja2LaserTeksti);
1392
1393        PushButton kayttajaNimiNappi = new PushButton("Muuta");
1394        kayttajaNimiNappi.Color = Color.Green;
1395        kayttajaNimiNappi.Position = new Vector(0.0, pelaaja2LaserNappi.Position.Y - 50);
1396        kayttajaNimiNappi.Clicked += delegate
1397        {
1398            InputWindow kayttajanimiIkkuna = new InputWindow("");
1399            kayttajanimiIkkuna.Color = Color.Transparent;
1400            kayttajanimiIkkuna.InputBox.BorderColor = Color.Green;
1401            kayttajanimiIkkuna.InputBox.Text = AsetustenKaytto.Asetukset.KayttajaNimi;
1402            kayttajanimiIkkuna.InputBox.Cursor.Color = Color.Green;
1403            kayttajanimiIkkuna.Position = new Vector(0.0, kayttajaNimiNappi.Y - 50);
1404            kayttajanimiIkkuna.OKButton.Color = Color.Green;
1405            kayttajanimiIkkuna.OKButton.Clicked += delegate
1406            {
1407                AsetustenKaytto.Asetukset.KayttajaNimi = kayttajanimiIkkuna.InputBox.Text;
1408                AsetustenKaytto.TallennaAsetukset();
1409                LuoAsetusIkkuna();
1410            };
1411            Add(kayttajanimiIkkuna);
1412        };
1413        Add(kayttajaNimiNappi);
1414
1415        Label kayttajanimiTeksti = new Label("Käyttäjänimi: ");
1416        kayttajanimiTeksti.Position = new Vector(kayttajaNimiNappi.X - 150, kayttajaNimiNappi.Y);
1417        Add(kayttajanimiTeksti);
1418    }
1419
1420    /// <summary>
1421    /// Pelimuotovalikon luonti.
1422    /// </summary>
1423    void LuoPelimuodonValintaValikko()
1424    {
1425        AnimatedMultiSelectWindow pelimuotoValikko = new AnimatedMultiSelectWindow("Valitse pelimuoto", valikonPainikeKuva, "Deathmatch", "Infinite", "Sandbox", "Takaisin");
1426        pelimuotoValikko.ItemSelected += PainettiinPelimuotoValikonNappia;
1427        pelimuotoValikko.Color = Color.Transparent;
1428        pelimuotoValikko.BorderColor = Color.Transparent;
1429        Level.Background.Image = valikonKuva;
1430        Level.BackgroundColor = Color.Black;
1431        pelimuotoValikko.DefaultCancel = 2;
1432        Add(pelimuotoValikko);
1433    }
1434
1435    /// <summary>
1436    /// Pelimuotovalikon nappien painalluksen käsittely.
1437    /// </summary>
1438    /// <param name="valinta">Painettu nappi.</param>
1439    void PainettiinPelimuotoValikonNappia(int valinta)
1440    {
1441        switch (valinta)
1442        {
1443            case 0:
1444                LuoPelinKustomointiIkkuna();
1445                break;
1446            case 1:
1447                LuoInfinitePeliMuodonValintaValikko();
1448                break;
1449            case 2:
1450                Level.Background.Image = null;
1451                ValittuKenttaTiedosto = "kenttä2"; // turha
1452                LuoKentta(2, 2, false);
1453                OnkoSatunnaisKentta = false;
1454                ClearControls();
1455                AsetaOhjaimet();
1456                AsetaSandboxOhjaimet();
1457                SoitaMusiikkia(3); // Sandbox: vanha OrcsCome
1458                Partikkelit.PoistaValikkoTaustaPartikkelit();
1459                break;
1460            case 3:
1461                LuoAlkuValikko();
1462                break;
1463        }
1464    }
1465
1466    void LuoInfinitePeliMuodonValintaValikko()
1467    {
1468        AnimatedMultiSelectWindow infinitePelimuotoValikko = new AnimatedMultiSelectWindow("Valitse pelimuoto", valikonPainikeKuva, "Infinite", "Escape", "Takaisin");
1469        infinitePelimuotoValikko.ItemSelected += PainettiinInfinitePelimuotoValikonNappia;
1470        infinitePelimuotoValikko.Color = Color.Transparent;
1471        infinitePelimuotoValikko.BorderColor = Color.Transparent;
1472        Level.Background.Image = valikonKuva;
1473        Level.BackgroundColor = Color.Black;
1474        infinitePelimuotoValikko.DefaultCancel = 2;
1475        Add(infinitePelimuotoValikko);
1476
1477    }
1478
1479    void PainettiinInfinitePelimuotoValikonNappia(int valinta)
1480    {
1481        switch (valinta)
1482        {
1483            case 0:
1484                LuoInfinitevalikko();
1485                break;
1486            case 1:
1487                LuoEscapeValikko(); 
1488                break;
1489            case 2:
1490                LuoPelimuodonValintaValikko();
1491                break;
1492        }
1493    }
1494
1495    void LuoEscapeValikko()
1496    {
1497        List<Widget> ikkunanKomponentit = new List<Widget>();
1498
1499        MultiSelectWindow valikko = new MultiSelectWindow("Escapen kustomointi", "Yksinpeli", "Moninpeli", "Takaisin");
1500        valikko.ItemSelected += delegate(int valinta) { PainettiinEscapenKustomointiIkkunanNappia(valinta, ikkunanKomponentit); };
1501        valikko.Color = Color.Transparent;
1502        valikko.SelectionColor = Color.Green;
1503        valikko.BorderColor = Color.Transparent;
1504        Level.Background.Image = valikonKuva;
1505        Level.BackgroundColor = Color.Black;
1506        valikko.DefaultCancel = 2;
1507        valikko.Position = new Vector(0.0, Screen.Top - valikko.Height);
1508        Add(valikko);
1509
1510        MonestakoVoittaa = new IntMeter(5, 1, 100);
1511
1512        Slider kuolematJoillaHaviaa = new Slider(300.0, 20.0);
1513        kuolematJoillaHaviaa.Position = new Vector(valikko.X, valikko.Y - 200);
1514        Add(kuolematJoillaHaviaa);
1515        kuolematJoillaHaviaa.BorderColor = Color.Transparent;
1516        kuolematJoillaHaviaa.Color = Color.Transparent;
1517        kuolematJoillaHaviaa.Knob.Color = Color.Green;
1518        kuolematJoillaHaviaa.Track.Color = Color.DarkGreen;
1519        kuolematJoillaHaviaa.BindTo(KauankoPuolustetaan);
1520        ikkunanKomponentit.Add(kuolematJoillaHaviaa);
1521
1522        Label kuolematJoillaHaviaaOtsikko = new Label("Tappoja voittoon:");
1523        kuolematJoillaHaviaaOtsikko.Position = new Vector(kuolematJoillaHaviaa.X - kuolematJoillaHaviaa.Width, kuolematJoillaHaviaa.Y);
1524        Add(kuolematJoillaHaviaaOtsikko);
1525        ikkunanKomponentit.Add(kuolematJoillaHaviaaOtsikko);
1526
1527        Label kuolematJoillaHaviaaNaytto = new Label();
1528        kuolematJoillaHaviaaNaytto.BindTo(MonestakoVoittaa);
1529        kuolematJoillaHaviaaNaytto.Position = new Vector(kuolematJoillaHaviaa.X + kuolematJoillaHaviaa.Width / 1.5, kuolematJoillaHaviaa.Y);
1530        Add(kuolematJoillaHaviaaNaytto);
1531        ikkunanKomponentit.Add(kuolematJoillaHaviaaNaytto);
1532    }
1533
1534    void PainettiinEscapenKustomointiIkkunanNappia(int valinta, List<Widget> ikkunanKomponentit)
1535    {
1536        foreach (Widget k in ikkunanKomponentit)
1537        {
1538            k.Destroy();
1539        }
1540
1541        switch (valinta)
1542        {
1543            case 0:
1544                AloitaEscapeGame(1, 1, KauankoPuolustetaan);
1545                break;
1546            case 1:
1547                break;
1548            case 2:
1549                break;
1550           
1551        }
1552    }
1553
1554
1555    /// <summary>
1556    /// Pelin kustomointi-ikkunan luonti.
1557    /// </summary>
1558    void LuoPelinKustomointiIkkuna()
1559    {
1560        List<Widget> ikkunanKomponentit = new List<Widget>();
1561        OnOffButton ulkonakoValitsin = new OnOffButton(25, 25, false);
1562
1563
1564        MultiSelectWindow valikko = new MultiSelectWindow("Pelin kustomointi", "Klassinen mäppi", "Satunnaisgeneroitu mäppi", "Takaisin");
1565        valikko.ItemSelected += delegate(int valinta) { PainettiinPelinKustomointiIkkunanNappia(valinta, ikkunanKomponentit, ulkonakoValitsin.IsPressed); };
1566        valikko.Color = Color.Transparent;
1567        valikko.SelectionColor = Color.Green;
1568        valikko.BorderColor = Color.Transparent;
1569        Level.Background.Image = valikonKuva;
1570        Level.BackgroundColor = Color.Black;
1571        valikko.DefaultCancel = 2;
1572        valikko.Position = new Vector(0.0, Screen.Top - valikko.Height);
1573        Add(valikko);
1574
1575        MonestakoVoittaa = new IntMeter(5, 1, 100);
1576
1577        Slider tapotJoillaVoittaa = new Slider(300.0, 20.0);
1578        tapotJoillaVoittaa.Position = new Vector(valikko.X, valikko.Y - 200);
1579        Add(tapotJoillaVoittaa);
1580        tapotJoillaVoittaa.BorderColor = Color.Transparent;
1581        tapotJoillaVoittaa.Color = Color.Transparent;
1582        tapotJoillaVoittaa.Knob.Color = Color.Green;
1583        tapotJoillaVoittaa.Track.Color = Color.DarkGreen;
1584        tapotJoillaVoittaa.BindTo(MonestakoVoittaa);
1585        ikkunanKomponentit.Add(tapotJoillaVoittaa);
1586
1587        Label tapotJoillaVoittaaOtsikko = new Label("Tappoja voittoon:");
1588        tapotJoillaVoittaaOtsikko.Position = new Vector(tapotJoillaVoittaa.X - tapotJoillaVoittaa.Width, tapotJoillaVoittaa.Y);
1589        Add(tapotJoillaVoittaaOtsikko);
1590        ikkunanKomponentit.Add(tapotJoillaVoittaaOtsikko);
1591
1592        Label tapotJoillaVoittaaNaytto = new Label();
1593        tapotJoillaVoittaaNaytto.BindTo(MonestakoVoittaa);
1594        tapotJoillaVoittaaNaytto.Position = new Vector(tapotJoillaVoittaa.X + tapotJoillaVoittaa.Width / 1.5, tapotJoillaVoittaa.Y);
1595        Add(tapotJoillaVoittaaNaytto);
1596        ikkunanKomponentit.Add(tapotJoillaVoittaaNaytto);
1597
1598        ulkonakoValitsin.ColorWhileOn = Color.Green;
1599        ulkonakoValitsin.ColorWhileOff = Color.Red;
1600        ulkonakoValitsin.Position = new Vector(tapotJoillaVoittaa.X, tapotJoillaVoittaa.Y - 50);
1601        Add(ulkonakoValitsin);
1602        ikkunanKomponentit.Add(ulkonakoValitsin);
1603
1604        Label ulkoNakoValitsinOtsikko = new Label("Vaihtoehtoinen grafiikkateema:");
1605        ulkoNakoValitsinOtsikko.Y = ulkonakoValitsin.Y;
1606        ulkoNakoValitsinOtsikko.Left = tapotJoillaVoittaaOtsikko.Left;
1607        Add(ulkoNakoValitsinOtsikko);
1608        ikkunanKomponentit.Add(ulkoNakoValitsinOtsikko);
1609    }
1610
1611    /// <summary>
1612    /// Handleri pelin kustomointinäytön napeille.
1613    /// </summary>
1614    /// <param name="valinta">Valittu nappi.</param>
1615    /// <param name="poistettavatIkkunanKomponentit">Mitkä kaikki poistetaan, kun nappia painetaan.</param>
1616    void PainettiinPelinKustomointiIkkunanNappia(int valinta, List<Widget> poistettavatIkkunanKomponentit, bool kaytetaankoVaihtoEhtoistaUlkonakoa)
1617    {
1618        foreach (Widget ikkunanKomponentti in poistettavatIkkunanKomponentit)
1619        {
1620            ikkunanKomponentti.Destroy();
1621        }
1622
1623        switch (valinta)
1624        {
1625            case 0:
1626                Level.Background.Image = null;
1627                ValittuKenttaTiedosto = "kenttä2"; // kenttä2
1628                LuoKentta(0, 2, false);
1629                ClearControls();
1630                AsetaOhjaimet();
1631                SoitaMusiikkia(1); // DarkLurk deathmatchiin
1632                Partikkelit.PoistaValikkoTaustaPartikkelit();
1633                if (kaytetaankoVaihtoEhtoistaUlkonakoa)
1634                {
1635                    Level.Background.Image = LoadImage("Pohja_testi");
1636                    Camera.StayInLevel = true;
1637                    Level.AmbientLight = 0.0;
1638                }
1639                break;
1640            case 1:
1641                Level.Background.Image = null;
1642                ValittuKenttaTiedosto = "kenttä2";
1643                LuoKentta(1, 2, false);
1644                OnkoSatunnaisKentta = true;
1645                ClearControls();
1646                AsetaOhjaimet();
1647                SoitaMusiikkia(1); // DarkLurk deathmatchiin
1648                Partikkelit.PoistaValikkoTaustaPartikkelit();
1649                break;
1650            case 2:
1651                LuoPelimuodonValintaValikko();
1652                break;
1653        }
1654    }
1655
1656    /// <summary>
1657    /// Infinitevalikon luonti.
1658    /// </summary>
1659    void LuoInfinitevalikko()
1660    {
1661        List<Widget> ikkunanKomponentit = new List<Widget>();
1662        IntMeter monestakoHaviaa = new IntMeter(1, 0, 100);
1663        Level.Background.Image = null;
1664        MultiSelectWindow infinitevalikko = new MultiSelectWindow("Valitse pelaajien määrä", "Yksinpeli", "Moninpeli", "Takaisin");
1665        infinitevalikko.ItemSelected += delegate(int valinta) { PainettiinInfiniteMenunNappia(valinta, monestakoHaviaa.Value, ikkunanKomponentit); };
1666        infinitevalikko.Color = Color.Transparent;
1667        infinitevalikko.SelectionColor = Color.Green;
1668        infinitevalikko.BorderColor = Color.Transparent;
1669        infinitevalikko.Position = new Vector(0.0, Screen.Top - infinitevalikko.Height);
1670        Level.Background.Image = valikonKuva;
1671        infinitevalikko.DefaultCancel = 2;
1672        Add(infinitevalikko);
1673
1674        Slider kuolematJoillaHaviaa = new Slider(300.0, 20.0);
1675        kuolematJoillaHaviaa.Position = new Vector(infinitevalikko.X, infinitevalikko.Y - 200);
1676        Add(kuolematJoillaHaviaa);
1677        kuolematJoillaHaviaa.BorderColor = Color.Transparent;
1678        kuolematJoillaHaviaa.Color = Color.Transparent;
1679        kuolematJoillaHaviaa.Knob.Color = Color.Green;
1680        kuolematJoillaHaviaa.Track.Color = Color.DarkGreen;
1681        kuolematJoillaHaviaa.BindTo(monestakoHaviaa);
1682        ikkunanKomponentit.Add(kuolematJoillaHaviaa);
1683
1684        Label kuolematJoillaHaviaaOtsikko = new Label("Respauksia käytössä:");
1685        kuolematJoillaHaviaaOtsikko.Position = new Vector(kuolematJoillaHaviaa.X - kuolematJoillaHaviaa.Width, kuolematJoillaHaviaa.Y);
1686        Add(kuolematJoillaHaviaaOtsikko);
1687        ikkunanKomponentit.Add(kuolematJoillaHaviaaOtsikko);
1688
1689        Label kuolematJoillaHaviaaNaytto = new Label();
1690        kuolematJoillaHaviaaNaytto.BindTo(monestakoHaviaa);
1691        kuolematJoillaHaviaaNaytto.Position = new Vector(kuolematJoillaHaviaa.X + kuolematJoillaHaviaa.Width / 1.5, kuolematJoillaHaviaa.Y);
1692        Add(kuolematJoillaHaviaaNaytto);
1693        ikkunanKomponentit.Add(kuolematJoillaHaviaaNaytto);
1694
1695    }
1696
1697    /// <summary>
1698    /// Infinitevalikon napin painalluksen käsittely.
1699    /// </summary>
1700    /// <param name="valinta">Mitä painettiin.</param>
1701    /// <param name="monestakoPoikki">Monestako peli menee poikki.</param>
1702    /// <param name="poistettavatJutut">Pitä poistetaan, kun nappia painetaan.</param>
1703    void PainettiinInfiniteMenunNappia(int valinta, int monestakoPoikki, List<Widget> poistettavatJutut)
1704    {
1705        foreach (Widget poistettava in poistettavatJutut)
1706        {
1707            poistettava.Destroy();
1708        }
1709
1710        switch (valinta)
1711        {
1712            case 0: // Infiniten yksinpeli
1713                Level.Background.Image = null;
1714                ValittuKenttaTiedosto = "zombimäppi1"; // zombimäppi1
1715                ClearControls();
1716                SoitaMusiikkia(4); // OrcsCome Special
1717                AloitaInfiniteGame(1, 0, monestakoPoikki);
1718                AsetaOhjaimet();
1719                Partikkelit.PoistaValikkoTaustaPartikkelit();
1720                break;
1721
1722            case 1: // Infiniten kaksinpeli
1723                Level.Background.Image = null;
1724                ValittuKenttaTiedosto = "zombimäppi1";
1725                ClearControls();
1726                SoitaMusiikkia(4); // OrcsCome Special
1727                AloitaInfiniteGame(2, 0, monestakoPoikki);
1728                AsetaOhjaimet();
1729                Partikkelit.PoistaValikkoTaustaPartikkelit();
1730                break;
1731            case 2:
1732                LuoPelimuodonValintaValikko();
1733                break;
1734        }
1735    }
1736
1737    /// <summary>
1738    /// Luodaan pausevalikko.
1739    /// </summary>
1740    void LuoPauseValikko()
1741    {
1742        IsPaused = true;
1743        MultiSelectWindow valikko = new MultiSelectWindow("TAUKO", "Takaisin peliin", "Päävalikkoon", "Poistu pelistä");
1744        valikko.ItemSelected += PainettiinPauseValikonNappia;
1745        valikko.Color = Color.Transparent;
1746        valikko.BorderColor = Color.Transparent;
1747        valikko.SelectionColor = Color.Green;
1748        valikko.DefaultCancel = 0;
1749        Add(valikko);
1750    }
1751
1752    /// <summary>
1753    /// Pausevalikon nappien painalluksen käsittely.
1754    /// </summary>
1755    /// <param name="valinta">Painettu nappi.</param>
1756    void PainettiinPauseValikonNappia(int valinta)
1757    {
1758        switch (valinta)
1759        {
1760            case 0:
1761                IsPaused = false;
1762                break;
1763            case 1:
1764                IsPaused = false;
1765                PaaValikkoon();
1766                break;
1767            case 2:
1768                Exit();
1769                break;
1770        }
1771    }
1772
1773    #endregion
1774
1775    #region infinite
1776
1777    /// <summary>
1778    /// Aloitetaan uusi Infinite-peli.
1779    /// </summary>
1780    /// <param name="pelaajienMaara">Montako pelaajaa peliin tulee.</param>
1781    /// <param name="kenttaTyyppi">Millaista kenttää käytetään.</param>
1782    /// <param name="monestakoRespauksestaPoikki">Monestako respauksesta peli menee poikki.-</param>
1783    void AloitaInfiniteGame(int pelaajienMaara, int kenttaTyyppi, int monestakoRespauksestaPoikki)
1784    {
1785        Infinite infinite = new Infinite(monestakoRespauksestaPoikki);
1786        LuoKentta(kenttaTyyppi, pelaajienMaara, true);
1787        LuoVihollistenMallineet(infinite);
1788        infinite.PeliPaattyi += InfiniteHavio;
1789        infinite.VihollistenSpawnausAjastin.Timeout += delegate { SpawnaaInfinitenVihollisia(infinite); };
1790        foreach (Pelaaja p in pelaajat)
1791        {
1792            p.Kuoli += infinite.PelaajaKuoli;
1793        }
1794
1795        if (kenttaTyyppi == 0)
1796        {
1797            infinite.KaytetaankoFixedSpawneja = true;
1798            //AsetaFixedSpawnitInfiniteen(infinite);
1799        }
1800        Level.AmbientLight = 0.4;
1801        if (pelaajienMaara == 1) Level.AmbientLight = 0.7; // koska taskulamppu
1802    }
1803
1804    /// <summary>
1805    /// Luodaan Infinitessä käytettävien vihollisten mallineet
1806    /// ja annetaan ne Infinite-pelimuodon spawnauslistaan.
1807    /// </summary>
1808    /// <param name="peli">Peli, johon viholliset lisätään.</param>
1809    void LuoVihollistenMallineet(Infinite peli)
1810    {
1811        // Tavallinen zombi
1812        Vihollinen zombi = new Vihollinen(normaaliZombiKuva.Width / 1.2, normaaliZombiKuva.Height / 1.2, normaaliZombiKuva, 20, 12, 100, pelaajat, false, false, this, peli); // nopeus oli 4
1813        peli.LisaaVihollinenPeliin(zombi);
1814
1815        // Zombi, jolla on ase
1816        /*Vihollinen ampuvaZombi = new Vihollinen(ampuvaZombiKuva.Width / 1.2, ampuvaZombiKuva.Height / 1.2, ampuvaZombiKuva, 20, 4, 100, pelaajat, true, false, this, peli);
1817        ampuvaZombi.AmpumisTarkkuus = 6.0;
1818        ampuvaZombi.EtaisyysJoltaAmpuu = 300.0;
1819        ampuvaZombi.ValittuAse = Aseet.LuoRynkky();
1820        ampuvaZombi.ValittuAse.AanenVoimakkuus = 0.5;
1821        ampuvaZombi.TodennakoisyysSpawnata = 0.3;
1822        peli.LisaaVihollinenPeliin(ampuvaZombi);*/
1823
1824        // Itsetuhoinen parasiitti
1825        /*Vihollinen parasiitti = new Vihollinen(10, 10, RandomGen.SelectOne<Image>(parasiittienKuvat), 1, 2, 200, pelaajat, false, true, this);
1826        parasiitti.KuolemaEfektinPartikkeliKuva = RandomGen.SelectOne<Image>(parasiittienPartikkeliKuvat);
1827        peli.LisaaVihollinenPeliin(parasiitti); */
1828    }
1829
1830    /// <summary>
1831    /// Spawnataan viholliset Infiniten spawnauslistasta.
1832    /// </summary>
1833    /// <param name="peli">Peli, jonka spawnauslistasta viholliset spawnataan.</param>
1834    void SpawnaaInfinitenVihollisia(Infinite peli)
1835    {
1836        foreach (Vihollinen vihu in peli.TallaSpawnauskerrallaSpawnattavatViholliset)
1837        {
1838            vihu.Destroyed += delegate { peli.VihollisiaTapettu.Value++; };
1839            Add(vihu);
1840            Vector paikka;
1841            if (peli.KaytetaankoFixedSpawneja && peli.VihollistenFixedSpawnit.Count != 0)
1842            {
1843                do
1844                {
1845                    paikka = RandomGen.SelectOne<Vector>(peli.VihollistenFixedSpawnit);
1846                } while (!OnkoNaytonAlueella(paikka));
1847                vihu.Position = paikka;
1848            }
1849            else vihu.Position = ArvoSpawnausPaikkaKentanLaidoilta(Vakiot.PALJONKO_VIHOLLISET_SPAWNAAVAT_KENTAN_RAJOJEN_ULKOPUOLELLE);
1850
1851            peli.VihollisetKentalla.Add(vihu);
1852        }
1853    }
1854
1855    /// <summary>
1856    /// Arvotaan satunnainen paikka kentän rajojen ulkopuolelta.
1857    /// </summary>
1858    /// <param name="paljonkoLaitojenUlkopuolelle">Paljonko paikka tulee kentän rajojen ulkopuolelle.</param>
1859    /// <returns>Satunnainen paikka kentän laidoilta.</returns>
1860    Vector ArvoSpawnausPaikkaKentanLaidoilta(double paljonkoLaitojenUlkopuolelle)
1861    {
1862        //Arvotaan satunnainen vektori kentän joka laidalle, ja arvotaan joku niistä
1863        Vector[] vaihtoehdot = new Vector[4];
1864        vaihtoehdot[0] = RandomGen.NextVector(Vakiot.PELAAJAN_PIENIN_SALLITTU_X_KENTALLA - paljonkoLaitojenUlkopuolelle, Vakiot.PELAAJAN_PIENIN_SALLITTU_Y_KENTALLA,
1865            Vakiot.PELAAJAN_PIENIN_SALLITTU_X_KENTALLA - paljonkoLaitojenUlkopuolelle, Vakiot.PELAAJAN_SUURIN_SALLITTU_Y_KENTALLA); // vasen reuna
1866
1867        vaihtoehdot[1] = RandomGen.NextVector(Vakiot.PELAAJAN_PIENIN_SALLITTU_X_KENTALLA, Vakiot.PELAAJAN_SUURIN_SALLITTU_Y_KENTALLA + paljonkoLaitojenUlkopuolelle,
1868            Vakiot.PELAAJAN_SUURIN_SALLITTU_X_KENTALLA, Vakiot.PELAAJAN_SUURIN_SALLITTU_Y_KENTALLA + paljonkoLaitojenUlkopuolelle); // yläreuna
1869
1870        vaihtoehdot[2] = RandomGen.NextVector(Vakiot.PELAAJAN_SUURIN_SALLITTU_X_KENTALLA + paljonkoLaitojenUlkopuolelle, Vakiot.PELAAJAN_PIENIN_SALLITTU_Y_KENTALLA,
1871            Vakiot.PELAAJAN_SUURIN_SALLITTU_X_KENTALLA + paljonkoLaitojenUlkopuolelle, Vakiot.PELAAJAN_SUURIN_SALLITTU_Y_KENTALLA); // oikea reuna
1872
1873        vaihtoehdot[3] = RandomGen.NextVector(Vakiot.PELAAJAN_PIENIN_SALLITTU_X_KENTALLA, Vakiot.PELAAJAN_PIENIN_SALLITTU_Y_KENTALLA - paljonkoLaitojenUlkopuolelle,
1874            Vakiot.PELAAJAN_SUURIN_SALLITTU_X_KENTALLA, Vakiot.PELAAJAN_PIENIN_SALLITTU_Y_KENTALLA - paljonkoLaitojenUlkopuolelle); // alareuna
1875        return RandomGen.SelectOne<Vector>(vaihtoehdot); // palautetaan yksi neljästä
1876    }
1877
1878    /// <summary>
1879    /// Asetetaan Infiniten fixed-spawnit normimäppiä varten.
1880    /// </summary>
1881    /// <param name="peli"></param>
1882    void AsetaFixedSpawnitInfiniteen(Infinite peli)
1883    {
1884        peli.VihollistenFixedSpawnit.Add(new Vector(0, -900));
1885        peli.VihollistenFixedSpawnit.Add(new Vector(960, -270));
1886        peli.VihollistenFixedSpawnit.Add(new Vector(-960, -270));
1887        peli.VihollistenFixedSpawnit.Add(new Vector(0, 1640));
1888        peli.VihollistenFixedSpawnit.Add(new Vector(1300, 920));
1889        peli.VihollistenFixedSpawnit.Add(new Vector(-1300, 920));
1890    }
1891
1892    #endregion
1893
1894    #region Escape
1895
1896    void AloitaEscapeGame(int pelaajienMaara, int respaustenMaara, double puolustettavaAika)
1897    {
1898        List<Pelaaja> pelaajatList = new List<Pelaaja>(pelaajat);
1899
1900        LuoKentta(0, pelaajienMaara, true);
1901
1902        Escape escapeGame = new Escape(respaustenMaara, puolustettavaAika, pelaajatList);
1903
1904        LuoVihollistenMallineet(escapeGame);
1905        escapeGame.PeliPaattyi += InfiniteHavio;
1906        escapeGame.VihollistenSpawnausAjastin.Timeout += delegate { SpawnaaInfinitenVihollisia(escapeGame); };
1907        foreach (Pelaaja p in pelaajat)
1908        {
1909            p.Kuoli += escapeGame.PelaajaKuoli;
1910        }
1911
1912        escapeGame.KaytetaankoFixedSpawneja = true;
1913        Level.AmbientLight = 0.4;
1914        if (pelaajienMaara == 1) Level.AmbientLight = 0.7; // koska taskulamppu
1915    }
1916
1917    #endregion
1918
1919    #region pelaaja
1920
1921    /// <summary>
1922    /// Luodaan uusi pelaaja.
1923    /// </summary>
1924    /// <param name="paikka">Paikka, johon pelaaja luodaan ja johon se respawnaa.</param>
1925    /// <param name="leveys">Pelaajan leveys.</param>
1926    /// <param name="korkeus">Pelaajan korkeus.</param>
1927    /// <param name="numero">Pelaajan numero.</param>
1928    /// <param name="kuva">Pelaajan kuva.</param>
1929    /// <param name="kamanVari">Pelaajaan viittaavien objektien väri.</param>
1930    /// <param name="kaytetaankoLaseria">Onko pelaajalla lasertähtäin vai tavallinen piste.</param>
1931    /// <param name="hudinPaikka">Pelaajan HUD:in paikka.</param>
1932    /// <returns>Pelaaja.</returns>
1933    public Pelaaja LuoPelaaja(Vector paikka, double leveys, double korkeus, int numero, Image kuva, Color kamanVari, bool kaytetaankoLaseria, Vector hudinPaikka, bool kaytetaankoTaskulamppua)
1934    {
1935        Pelaaja pelaaja = new Pelaaja(leveys, korkeus, kaytetaankoLaseria, kaytetaankoTaskulamppua); // true: käytetäänkö taskulamppua
1936        pelaaja.CanRotate = false;
1937        pelaaja.Tag = "pelaaja";
1938        pelaaja.LisaaAse(Aseet.LuoPistooli());
1939        pelaaja.LisaaAse(Aseet.LuoNyrkki());
1940        pelaaja.Position = paikka;
1941        pelaaja.SpawnausPaikat.Add(paikka);
1942        pelaaja.Numero = numero;
1943        pelaaja.Image = kuva;
1944        pelaaja.LinearDamping = 0.80;
1945        pelaaja.objektienVari = kamanVari;
1946        pelaaja.elamaPalkki.BarColor = pelaaja.objektienVari;
1947        pelaaja.tahtain = LuoTähtäin(pelaaja.objektienVari);
1948        pelaaja.ValittuAseNaytto = LuoAseNäyttö(hudinPaikka);
1949        pelaaja.ValittuAseNaytto.Text = pelaaja.ValittuAse.AseenNimi;
1950        pelaaja.TappojenMaaraNaytto = LuoTappoNaytto(pelaaja.ValittuAseNaytto.Position);
1951        AddCollisionHandler<Pelaaja, Vihollinen>(pelaaja, delegate(Pelaaja p, Vihollinen v) { Damagea(pelaaja, v.TuhovoimaElaviaKohtaan); });
1952        if (kaytetaankoLaseria)
1953        {
1954            pelaaja.kaytetaankoPalloTahtainta = false;
1955            //pelaaja.tahtain.IsVisible = false;
1956            //AxleJoint aj = new AxleJoint(pelaaja.tahtain, pelaaja);
1957            //aj.Softness = 2;
1958            //Add(aj);
1959        }
1960        return pelaaja;
1961    }
1962
1963    /// <summary>
1964    /// Liikutetaan pelaajaa määrättyyn suuntaan näppäimistöllä.
1965    /// </summary>
1966    /// <param name="pelaaja">Pelaaja, jota liikutetaan.</param>
1967    /// <param name="suunta">Suunta, johon pelaajaa liikutetaan.</param>
1968    void LiikutaPelaajaa(Pelaaja pelaaja, Vector suunta)
1969    {
1970        pelaaja.Move(suunta * pelaaja.Nopeus);
1971    }
1972
1973    /// <summary>
1974    /// Liikutetaan pelaajaa määrättyyn suuntaan Xbox-ohjaimella.
1975    /// </summary>
1976    /// <param name="pelaaja">Pelaaja, jota liikutetaan.</param>
1977    /// <param name="tatinTila">Xbox-ohjaimen analogitatin asento.</param>
1978    void LiikutaPelaajaaPadilla(AnalogState tatinTila, Pelaaja pelaaja)
1979    {
1980        Vector tatinAsento = tatinTila.StateVector;
1981        pelaaja.Move(tatinAsento * pelaaja.Nopeus);
1982        pelaaja.tahtain.Move(tatinAsento * pelaaja.Nopeus);
1983    }
1984
1985    // Tässä kohdassa (LiikutaTahtainta, LiikutaTahtaintaPadilla) ongelmana samat parametrit, mutta eri sisältö.
1986
1987    /// <summary>
1988    /// Liikutetaan pelaajan tähtäintä hiirellä.
1989    /// </summary>
1990    /// <param name="hiirenTila">Ei käytössä, pakollinen parametri.</param>
1991    /// <param name="pelaaja">Pelaaja, jonka tähtäintä liikutetaan.</param>
1992    void LiikutaTahtainta(AnalogState hiirenTila, Pelaaja pelaaja)
1993    {
1994        pelaaja.tahtain.X = Mouse.PositionOnWorld.X;
1995        pelaaja.tahtain.Y = Mouse.PositionOnWorld.Y;
1996    }
1997
1998    /// <summary>
1999    /// Liikutetaan pelaajan tähtäintä Xbox-ohjaimella.
2000    /// </summary>
2001    /// <param name="pelaaja">Pelaaja, jonka tähtäintä liikutetaan.</param>
2002    /// <param name="tatinTila">Xbox-ohjaimen analogitatin asento.</param>
2003    void LiikutaTahtaintaPadilla(AnalogState tatinTila, Pelaaja pelaaja)
2004    {
2005        pelaaja.tahtain.Move(tatinTila.StateVector * 1500);
2006    }
2007
2008    /// <summary>
2009    /// Luodaan uusi tähtäin.
2010    /// </summary>
2011    /// <param name="vari">Tähtäimen väri.</param>
2012    /// <returns>Tähtäin.</returns>
2013    PhysicsObject LuoTähtäin(Color vari)
2014    {
2015        PhysicsObject tähtäin = new PhysicsObject(10.0, 10.0);
2016        tähtäin.Shape = Shape.Circle;
2017        tähtäin.Color = vari;
2018        tähtäin.IgnoresCollisionResponse = true;
2019        tähtäin.IgnoresExplosions = true;
2020        tähtäin.IgnoresPhysicsLogics = true;
2021        tähtäin.LinearDamping = 0.60;
2022        tähtäin.Tag = "tahtain";
2023        Add(tähtäin, 3);
2024        return tähtäin;
2025    }
2026
2027    Label LuoTappoNaytto(Vector ylemmanHudinOsanPaikka)
2028    {
2029        Label tapponaytto = new Label("Tappoja: 0");
2030        tapponaytto.TextColor = Color.White;
2031        tapponaytto.BorderColor = Color.Transparent;
2032        tapponaytto.Position = ylemmanHudinOsanPaikka - new Vector(0.0, 60.0);
2033        Add(tapponaytto);
2034        return tapponaytto;
2035    }
2036
2037    #endregion
2038
2039    #region aseiden toiminnot
2040
2041    /// <summary>
2042    /// Ammutaan pelaajan kulloinkin valittuna olevalla aseella ja
2043    /// luodaan ammukselle törmäyksenkäsittelijät.
2044    /// </summary>
2045    /// <param name="pelaaja">Pelaaja, jonka aseella ammutaan.</param>
2046    /// <param name="overridesIsReady">Annetaan aseen ampua, vaikka se ei oikeasti voisi. Jos true, ääntä ei toisteta.</param>
2047    void Ammu(Pelaaja pelaaja, bool overridesIsReady = false)
2048    {
2049        // pari tarpeellista tarkistusta
2050        if (!pelaaja.IsAddedToGame) return;
2051        if (pelaaja.ValittuAse == null) return;
2052        if (pelaaja.LadataankoAsetta) return;
2053
2054        //pelaaja.ValittuAse.IsReady = true;
2055        PhysicsObject ammus = pelaaja.ValittuAse.Shoot(overridesIsReady);
2056        if (ammus == null) return;
2057
2058        // laitetaan ammus satunnaiseen suuntaan aseen hajoaman mukaan
2059        Vector random = RandomGen.NextVector(pelaaja.ValittuAse.AseenHajoama.X, pelaaja.ValittuAse.AseenHajoama.Y);
2060        if (pelaaja == pelaajat[0])
2061        {
2062            ammusmittariNäyttö.Text = pelaajat[0].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[0].ValittuAse.MaxAmmo.Value.ToString();
2063            if (pelaaja.ValittuAse.OnkoMeleeAse == true) ammusmittariNäyttö.Text = "";
2064            if (pelaaja.ValittuAse.HyokkaysAnimaatio1 != null)
2065            {
2066                pelaajat[0].Animation = pelaaja.ValittuAse.HyokkaysAnimaatio1;
2067                pelaajat[0].Animation.Start(1);
2068            }
2069        }
2070
2071        if (pelaaja == pelaajat[1])
2072        {
2073            ammusmittariNäyttö2.Text = pelaajat[1].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[1].ValittuAse.MaxAmmo.Value.ToString();
2074            if (pelaaja.ValittuAse.OnkoMeleeAse == true) ammusmittariNäyttö2.Text = "";
2075            if (pelaaja.ValittuAse.HyokkaysAnimaatio2 != null)
2076            {
2077                pelaajat[1].Animation = pelaaja.ValittuAse.HyokkaysAnimaatio2;
2078                pelaajat[1].Animation.Start(1);
2079            }
2080        }
2081
2082        ammus.Hit(random);
2083        ammus.CollisionIgnoreGroup = 4;
2084        ammus.Tag = "ammus";
2085        ammus.LinearDamping = 0.99;
2086        ammus.Size = new Vector(pelaaja.ValittuAse.luodinKuva.Width, pelaaja.ValittuAse.luodinKuva.Height);
2087        ammus.Color = Color.White;
2088        ammus.Mass = 0.01;
2089        ammus.CanRotate = false;
2090
2091        // jos on meleease, ei näytetä ammusta
2092        if (pelaaja.ValittuAse.OnkoMeleeAse == true) ammus.IsVisible = false;
2093
2094        // muuten ammutaan hylsy ja laitetaan luodille oikea kuva
2095        else
2096        {
2097            if (pelaaja.ValittuAse.TuleekoHylsya)
2098                Hylsy(pelaaja, pelaaja.ValittuAse.hylsynKuva);
2099            ammus.Image = pelaaja.ValittuAse.luodinKuva;
2100        }
2101
2102        if (pelaaja.ValittuAse.UsesTracers)
2103        {
2104            ammus.IsUpdated = true;
2105            ammus.NeedsUpdateCall = true;
2106            Color c;
2107            if (pelaaja.ValittuAse.OverrideTracerColor != Color.Transparent)
2108                c = pelaaja.ValittuAse.OverrideTracerColor;
2109            else c = pelaaja.objektienVari;
2110            ammus.Updated += delegate(PhysicsObject o) { DrawTracers(o, c, pelaaja.ValittuAse.TracerLength, pelaaja.ValittuAse.TracerBrightness); };
2111        }
2112
2113        if (pelaaja.ValittuAse.IsHoming)
2114        {
2115            ammus.IsUpdated = true;
2116            ammus.NeedsUpdateCall = true;
2117            if (pelaaja == pelaajat[0])
2118                ammus.Updated += delegate(PhysicsObject o) { HakeuduKohteeseen(o, pelaajat[1], 750); };
2119            else
2120                ammus.Updated += delegate(PhysicsObject o) { HakeuduKohteeseen(o, pelaajat[0], 750); };
2121
2122        }
2123
2124        if (pelaaja.ValittuAse.LapaiseekoMateriaaleja)
2125        {
2126            ammus.IgnoresCollisionResponse = true;
2127            ammus.Collided += delegate
2128            {
2129                if (pelaaja.ValittuAse.AseenLapaisy > 0)
2130                    Timer.SingleShot(pelaaja.ValittuAse.AseenLapaisy, delegate { ammus.IgnoresCollisionResponse = false; });
2131            };
2132        }
2133
2134        AddCollisionHandler<PhysicsObject, Pelaaja>(
2135            ammus, delegate(PhysicsObject a, Pelaaja kohdepelaaja)
2136            {
2137                Damagea(kohdepelaaja, pelaaja.ValittuAse.TuhovoimaElaviaVastaan);
2138                Partikkelit.AddParticleEffect(Partikkelit.VeriPartikkelit, new Vector(a.X, a.Y), 40);
2139                osuma1.Play();
2140                if (ammus != null) ammus.Destroy();
2141            });
2142
2143        AddCollisionHandler<PhysicsObject, Vihollinen>(
2144            ammus, delegate(PhysicsObject a, Vihollinen kohde)
2145            {
2146                Damagea(kohde, pelaaja.ValittuAse.TuhovoimaElaviaVastaan);
2147                Partikkelit.AddParticleEffect(Partikkelit.VeriPartikkelit, new Vector(a.X, a.Y), 40);
2148                osuma1.Play();
2149                if (ammus != null) ammus.Destroy();
2150            });
2151
2152        AddCollisionHandler<PhysicsObject, Tuhoutuva>(
2153            ammus, delegate(PhysicsObject a, Tuhoutuva tuhoutuva)
2154        {
2155            if (tuhoutuva.IsStatic)
2156            {
2157                GameObject luodinJalki = new GameObject(12, 13);
2158                luodinJalki.Image = crack1;
2159                luodinJalki.Position = a.Position;
2160                luodinJalki.Angle = RandomGen.NextAngle();
2161                Add(luodinJalki, 1);
2162                LisaaTehosteObjekti(luodinJalki);
2163                tuhoutuva.Destroyed += delegate
2164                {
2165                    luodinJalki.Destroy();
2166                    tehosteet.Remove(luodinJalki);
2167                };
2168            }
2169
2170            if (pelaaja.ValittuAse.HaviaakoAmmusOsumasta && ammus.IgnoresCollisionResponse == false)
2171            {
2172                a.Destroy();
2173                a.NeedsUpdateCall = false;
2174                switch (RandomGen.NextInt(0, 5))
2175                {
2176                    case 0:
2177                        luotiOsuu.Play();
2178                        break;
2179                    case 1:
2180                        luotiOsuu2.Play();
2181                        break;
2182                    case 2:
2183                        luotiOsuu3.Play();
2184                        break;
2185                    case 3:
2186                        luotiOsuu4.Play();
2187                        break;
2188                    case 4:
2189                        luotiOsuu5.Play();
2190                        break;
2191                }
2192            }
2193            else if (ammus.IgnoresCollisionResponse == true) // ei tuhota
2194            {
2195                switch (RandomGen.NextInt(0, 5))
2196                {
2197                    case 0:
2198                        luotiOsuu.Play();
2199                        break;
2200                    case 1:
2201                        luotiOsuu2.Play();
2202                        break;
2203                    case 2:
2204                        luotiOsuu3.Play();
2205                        break;
2206                    case 3:
2207                        luotiOsuu4.Play();
2208                        break;
2209                    case 4:
2210                        luotiOsuu5.Play();
2211                        break;
2212                }
2213            }
2214            else
2215            {
2216                a.Velocity = new Vector(0.0, 0.0);
2217                a.IgnoresCollisionResponse = true;
2218            }
2219            //tuhoutuva.Kesto.Value -= pelaaja.ValittuAse.TuhovoimaTuhoutuviaVastaan;
2220            Damagea(tuhoutuva, pelaaja.ValittuAse.TuhovoimaTuhoutuviaVastaan);
2221        });
2222
2223        AddCollisionHandler<PhysicsObject, Tuhoutuva>(
2224            ammus, "kivi", delegate(PhysicsObject a, Tuhoutuva kivi)
2225            {
2226                Partikkelit.AddParticleEffect(Partikkelit.KiviPartikkelit, new Vector(a.X, a.Y), 30);
2227                Partikkelit.AddParticleEffect(Partikkelit.KipinaPartikkelit, new Vector(a.X, a.Y), 5);
2228            });
2229
2230        AddCollisionHandler<PhysicsObject, Tuhoutuva>(
2231            ammus, "puu", delegate(PhysicsObject a, Tuhoutuva puu)
2232            {
2233                Partikkelit.AddParticleEffect(Partikkelit.PuuPartikkelit, new Vector(a.X, a.Y), 40);
2234            });
2235        AddCollisionHandler<PhysicsObject, Helikopteri>(
2236            ammus, delegate(PhysicsObject a, Helikopteri kopteri)
2237            {
2238                if (kopteri.OnkoIlmassa) return;
2239
2240                Damagea(kopteri, pelaaja.ValittuAse.TuhovoimaElaviaVastaan);
2241                Partikkelit.AddParticleEffect(Partikkelit.KipinaPartikkelit, new Vector(a.X, a.Y), 40);
2242                a.Destroy();
2243            });
2244
2245        AddCollisionHandler<PhysicsObject, PhysicsObject>(
2246            ammus, "piikkilanka", delegate(PhysicsObject a, PhysicsObject piikkilanka)
2247            {
2248                Partikkelit.AddParticleEffect(Partikkelit.KipinaPartikkelit, new Vector(a.X, a.Y), 40);
2249                //ammus.Destroy();
2250            });
2251        AddCollisionHandler<PhysicsObject, PhysicsObject>(
2252            ammus, delegate(PhysicsObject a, PhysicsObject kohde)
2253            {
2254                if (ammus.IgnoresCollisionResponse == false) a.Destroy();
2255                a.NeedsUpdateCall = false;
2256            });
2257
2258
2259    }
2260
2261    /// <summary>
2262    /// Ammutaan haulikkotyyppisellä aseella.
2263    /// </summary>
2264    /// <param name="pelaaja">Pelaaja, jonka aseella ammutaan.</param>
2265    /// <param name="ammustenMaara">Montako ammusta ammutaan.</param>
2266    void AmmuHaulikolla(Pelaaja pelaaja, int ammustenMaara)
2267    {
2268        if (!pelaaja.ValittuAse.IsReady) return;
2269
2270        pelaaja.ValittuAse.AttackSound.Play();
2271        pelaaja.ValittuAse.Ammo.Value--;
2272        Hylsy(pelaaja, pelaaja.ValittuAse.hylsynKuva);
2273
2274        for (int i = 0; i < ammustenMaara; i++)
2275        {
2276            Ammu(pelaaja, true);
2277        }
2278    }
2279
2280    void MeleeIsku(Pelaaja pelaaja)
2281    {
2282        Ase edellinenAse = pelaaja.ValittuAse;
2283        pelaaja.ValitseAse("nyrkki");
2284        Ammu(pelaaja);
2285        pelaaja.ValitseAse(edellinenAse.Tag.ToString());
2286        PaivitaPelaajanKuvaJaHUD(pelaaja);
2287    }
2288
2289    /// <summary>
2290    /// Ladataan pelaajan kulloinkin valittuna oleva ase.
2291    /// </summary>
2292    /// <param name="pelaaja">Pelaaja, jonka ase ladataan.</param>
2293    void Lataa(Pelaaja pelaaja)
2294    {
2295        // Ammo.Value == valitun aseen senhetkinen lippaassa oleva ammusmäärä
2296        // Ammo.MaxValue == valitun aseen maksimimäärä ammuksia lippaassa
2297        // MaxAmmo.Value == valitun aseen kokonaisammusten maksimimäärä
2298
2299        // jos ammukset täynnä, ei tehdä mitään
2300        if (pelaaja.ValittuAse.Ammo.Value == pelaaja.ValittuAse.Ammo.MaxValue)
2301        {
2302            pelaaja.LadataankoAsetta = false;
2303            return;
2304        }
2305
2306        // montako ammusta on käytetty lippaasta
2307        int lippaastaKaytettyjaAmmuksia = pelaaja.ValittuAse.Ammo.MaxValue - pelaaja.ValittuAse.Ammo.Value;
2308        aseLatausAani.Play();
2309        if (pelaaja.ValittuAse.MaxAmmo.Value >= pelaaja.ValittuAse.Ammo.MaxValue) pelaaja.ValittuAse.Ammo.Value = pelaaja.ValittuAse.Ammo.MaxValue;
2310        else pelaaja.ValittuAse.Ammo.Value = pelaaja.ValittuAse.MaxAmmo.Value;
2311
2312        pelaaja.ValittuAse.MaxAmmo.Value -= lippaastaKaytettyjaAmmuksia;
2313
2314        if (pelaaja == pelaajat[0])
2315        {
2316            ammusmittariNäyttö.Text = pelaajat[0].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[0].ValittuAse.MaxAmmo.Value.ToString();
2317        }
2318        if (pelaaja == pelaajat[1])
2319        {
2320            ammusmittariNäyttö2.Text = pelaajat[1].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[1].ValittuAse.MaxAmmo.Value.ToString();
2321        }
2322        pelaaja.LadataankoAsetta = false;
2323    }
2324
2325    /// <summary>
2326    /// Luo hylsyn pelaajan ampuessa ja lisää sen hylsyt-taulukkoon.
2327    /// </summary>
2328    /// <param name="pelaaja">Pelaaja, jonka aseesta hylsy lentää.</param>
2329    void Hylsy(Pelaaja pelaaja, Image hylsynkuva)
2330    {
2331        PhysicsObject hylsy = new PhysicsObject(2, 5);
2332        hylsy.Image = hylsynkuva;
2333        hylsy.Position = pelaaja.Position + Vector.FromLengthAndAngle(15, pelaaja.Angle + Angle.FromDegrees(-90));
2334        hylsy.LinearDamping = 0.93;
2335        hylsy.Mass = 0.5;
2336        hylsy.Angle = pelaaja.Angle + Angle.FromDegrees(90);
2337        hylsy.AngularVelocity = RandomGen.NextDouble(-20.0, 20.0);
2338        hylsy.AngularDamping = 0.97;
2339        Add(hylsy, -3);
2340
2341        hylsy.MaximumLifetime = TimeSpan.FromSeconds(1.5);
2342        hylsy.Destroying += delegate
2343        {
2344            GameObject fakeHylsy = new GameObject(hylsy.Width, hylsy.Height); // samanlainen GameObject-hylsy samaan paikkaan lagin vähentämiseksi
2345            fakeHylsy.Image = hylsynkuva;
2346            fakeHylsy.Position = hylsy.Position;
2347            fakeHylsy.Angle = hylsy.Angle;
2348            Add(fakeHylsy, -1);
2349            LisaaTehosteObjekti(fakeHylsy);
2350        };
2351
2352        hylsy.Hit(Vector.FromLengthAndAngle(RandomGen.NextInt(150, 300), pelaaja.Angle + Angle.FromDegrees(RandomGen.NextDouble(-95, -85))));
2353        AddCollisionHandler(hylsy, HylsyOsuu);
2354        Timer.SingleShot(0.5, delegate { hylsynPutoamisAani.Play(0.7, 0.0, 0.0); });
2355    }
2356
2357    /// <summary>
2358    /// CollisionHandleri hylsylle. Soitetaan kilahdusääni, jos hylsy osuu seinään.
2359    /// </summary>
2360    /// <param name="hylsy">Hylsy.</param>
2361    /// <param name="kohde">Kohde, johon hylsy osuu.</param>
2362    void HylsyOsuu(PhysicsObject hylsy, PhysicsObject kohde)
2363    {
2364        if (kohde is Tuhoutuva)
2365            hylsynPutoamisAani.Play(0.7, 0.0, 0.0);
2366    }
2367
2368    /// <summary>
2369    /// Heitetään kranaatti, jos pelaaja on lisätty ruudulle ja pelaajalla on kranaatteja jäljellä.
2370    /// </summary>
2371    /// <param name="pelaaja">Pelaaja, joka heittää kranaatin.</param>
2372    void HeitaKranaatti(Pelaaja pelaaja)
2373    {
2374        if (!pelaaja.IsAddedToGame || pelaaja.KranaattienMaara <= 0) return;
2375        const double KRANAATIN_NOPEUS = 25000;
2376        Grenade kranaatti = new Grenade(3.0, TimeSpan.FromSeconds(1.5));
2377        kranaatti.LinearDamping = 0.95;
2378        kranaatti.AngularVelocity = RandomGen.NextDouble(-5.0, 5.0);
2379        kranaatti.AngularDamping = 0.97;
2380        kranaatti.Image = kranaatinKuva;
2381        kranaatti.Explosion.Image = null;
2382        kranaatti.Explosion.ShockwaveColor = Color.Black;
2383        kranaatti.Explosion.IsShockwaveVisible = false;
2384        kranaatti.Explosion.Sound = Aseet.singonAani;
2385        kranaatti.Explosion.Speed = 2000;
2386        kranaatti.Explosion.MaxRadius = 500;
2387        kranaatti.Explosion.ShockwaveReachesObject += delegate(IPhysicsObject kohde, Vector shokki) { RajahdysOsuu(kohde, shokki, kranaatti.Position, Aseet.KRANAATIN_MAKSIMI_DAMAGE); };
2388        kranaatti.Destroying += delegate
2389        {
2390            Partikkelit.AddExplosionEffect(kranaatti.Position, 800);
2391            valo.Position = kranaatti.Position;
2392            valo.Intensity = 2.0;
2393            valo.Distance = 100;
2394            Timer.SingleShot(0.2, delegate { valo.Intensity = 1.5; });
2395            Timer.SingleShot(0.3, delegate { valo.Intensity = 1.0; });
2396            Timer.SingleShot(0.4, delegate { valo.Intensity = 0.5; });
2397            Timer.SingleShot(0.5, delegate { valo.Intensity = 0.0; });
2398        };
2399        kranaatti.Collided += delegate(IPhysicsObject k, IPhysicsObject kohde) { if (kohde.Tag.ToString() != "pelaaja") kranaatti.Velocity = Vector.Zero; };
2400        kranaatti.IsUpdated = true;
2401        kranaatti.NeedsUpdateCall = true;
2402        kranaatti.Updated += delegate(PhysicsObject p) { DrawTracers(kranaatti.Position, Color.Orange, 0.30, 6); }; // brightness 3
2403        pelaaja.Throw(kranaatti, Angle.FromDegrees(0), KRANAATIN_NOPEUS, 0, 0);
2404        pelaaja.KranaattienMaara--;
2405    }
2406
2407    /// <summary>
2408    /// Annetaan pelaajalle kamaa pelaajan törmätessä laatikkoon.
2409    /// </summary>
2410    /// <param name="laatikko">Laatikko, johon törmätään.</param>
2411    /// <param name="kohde">Pelaaja, joka törmää.</param>
2412    void AnnaKamaa(PhysicsObject laatikko, PhysicsObject kohde)
2413    {
2414        if (kohde.Tag.ToString() == "pelaaja")
2415        {
2416            Pelaaja pelaaja = (kohde as Pelaaja);
2417            Laatikko laat = (laatikko as Laatikko);
2418            Func<Ase>[] aseidenLuontimetodit = { Aseet.LuoRynkky, Aseet.LuoHaulikko, Aseet.LuoMinigun, Aseet.LuoSnipa, Aseet.LuoSinko, /*Aseet.LuoVarsijousi,*/ Aseet.LuoMagnum, Aseet.LuoVintorez };
2419
2420            if (laat.OnkoKäytössä == false)
2421            {
2422                //Ei voi ottaa kamaa käytetystä laatikosta
2423                return;
2424            }
2425            for (int i = 0; i < aseidenLuontimetodit.Length; i++)
2426            {
2427                Ase ase = aseidenLuontimetodit[i]();
2428                if (!pelaaja.OnkoPelaajallaAse(ase.Tag.ToString()))
2429                {
2430                    if (AikaKentanAlusta.SecondCounter.Value > ase.aikaJolloinVoiLuoda)
2431                    {
2432                        pelaaja.LisaaAse(ase);
2433                        MessageDisplay.Add("Pelaaja " + pelaaja.Numero + " sai aseen: " + ase.AseenNimi);
2434                        return;
2435                    }
2436                }
2437            }
2438            Ase satunnainenPelaajanAse;
2439            do
2440                satunnainenPelaajanAse = RandomGen.SelectOne<Ase>(pelaaja.Aseet);
2441            while (satunnainenPelaajanAse.OnkoMeleeAse);
2442
2443            satunnainenPelaajanAse.MaxAmmo.Value = satunnainenPelaajanAse.MaxAmmo.MaxValue;
2444            MessageDisplay.Add("Pelaaja " + pelaaja.Numero + " sai ammuksia aseeseen: " + satunnainenPelaajanAse.AseenNimi);
2445            pelaaja.KranaattienMaara++;
2446            MessageDisplay.Add("Pelaaja " + pelaaja.Numero + " sai kranaatin.");
2447
2448            laatikko.Image = kamaaNäkymätön;
2449            laatikko.IgnoresCollisionResponse = true;
2450            laat.OnkoKäytössä = false;
2451            laat.LaatikonAika.Start();
2452        }
2453    }
2454
2455    /// <summary>
2456    /// Luodaan näyttö, joka näyttää valitun aseen nimen.
2457    /// </summary>
2458    /// <param name="paikka">Näytön paikka.</param>
2459    /// <returns>Näyttö.</returns>
2460    Label LuoAseNäyttö(Vector paikka)
2461    {
2462        Label asenäyttö = new Label();
2463        Add(asenäyttö);
2464        asenäyttö.Position = paikka;
2465        asenäyttö.TextColor = Color.White;
2466        asenäyttö.BorderColor = Color.Transparent;
2467        asenäyttö.Tag = "HUD";
2468        return asenäyttö;
2469    }
2470
2471    /// <summary>
2472    /// Luodaan pelaajan 1 ammusmittari.
2473    /// </summary>
2474    void AmmusMittari()
2475    {
2476        IntMeter ammusmittari = new IntMeter(0);
2477        ammusmittariNäyttö = new Label(
2478        pelaajat[0].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[0].ValittuAse.MaxAmmo.Value.ToString());
2479        ammusmittariNäyttö.X = Screen.Left + 125;
2480        ammusmittariNäyttö.Y = Screen.Top - 100;
2481        ammusmittariNäyttö.TextColor = Jypeli.Color.White;
2482        ammusmittariNäyttö.BorderColor = Jypeli.Color.Transparent;
2483        Add(ammusmittariNäyttö);
2484    }
2485
2486    /// <summary>
2487    /// Luodaan pelaajan 2 ammusmittari.
2488    /// </summary>
2489    void AmmusMittari2()
2490    {
2491        IntMeter ammusmittari2 = new IntMeter(0);
2492        ammusmittariNäyttö2 = new Label(pelaajat[1].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[1].ValittuAse.MaxAmmo.Value.ToString());
2493        ammusmittariNäyttö2.X = Screen.Right - 125;
2494        ammusmittariNäyttö2.Y = Screen.Top - 100;
2495        ammusmittariNäyttö2.TextColor = Jypeli.Color.White;
2496        ammusmittariNäyttö2.BorderColor = Jypeli.Color.Transparent;
2497        Add(ammusmittariNäyttö2);
2498    }
2499
2500    /// <summary>
2501    /// Vaihdetaan asetta ja pelaajan kuvaa.
2502    /// </summary>
2503    /// <param name="pelaaja">Pelaaja, jonka asetta vaihdetaan.</param>
2504    /// <param name="vaihtosuunta">Suunta, johon aselistaa pyöritetään.</param>
2505    void VaihdaAsetta(Pelaaja pelaaja, int vaihtosuunta = 0)
2506    {
2507        if (pelaaja.AseidenMaara < 1) return;
2508        pelaaja.VaihdaAse(Mouse.WheelChange);
2509        pelaaja.VaihdaAse(vaihtosuunta);
2510
2511        PaivitaPelaajanKuvaJaHUD(pelaaja);
2512    }
2513
2514    void PaivitaPelaajanKuvaJaHUD(Pelaaja pelaaja)
2515    {
2516        if (pelaaja == pelaajat[0])
2517        {
2518            pelaaja.Image = pelaaja.ValittuAse.Pelaajan1AseKuva;
2519            ammusmittariNäyttö.Text = pelaajat[0].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[0].ValittuAse.MaxAmmo.Value.ToString();
2520            if (pelaaja.ValittuAse.OnkoMeleeAse == true) ammusmittariNäyttö.Text = "";
2521            pelaaja.ValittuAseNaytto.Text = pelaaja.ValittuAse.AseenNimi;
2522        }
2523
2524        if (pelaaja == pelaajat[1] && ammusmittariNäyttö2 != null)
2525        {
2526            pelaaja.Image = pelaaja.ValittuAse.Pelaajan2AseKuva;
2527            ammusmittariNäyttö2.Text = pelaajat[1].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[1].ValittuAse.MaxAmmo.Value.ToString();
2528            if (pelaaja.ValittuAse.OnkoMeleeAse == true) ammusmittariNäyttö2.Text = "";
2529            pelaaja.ValittuAseNaytto.Text = pelaaja.ValittuAse.AseenNimi;
2530        }
2531        pelaaja.ValittuAse.IsVisible = false;
2532    }
2533
2534    /// <summary>
2535    /// Ohjataan hakeutuvaa esinettä kohteeseen.
2536    /// </summary>
2537    /// <param name="hakeutuva">Hakeutuva esine.</param>
2538    /// <param name="kohde">Kohde, jota kohti hakeudutaan.</param>
2539    void HakeuduKohteeseen(PhysicsObject hakeutuva, PhysicsObject kohde, double nopeus)
2540    {
2541        if (hakeutuva.Brain.Owner != null) return;
2542
2543        FollowerBrain fb = new FollowerBrain(kohde);
2544        fb.Speed = nopeus;
2545        fb.TurnWhileMoving = true;
2546        hakeutuva.Brain = fb;
2547    }
2548
2549    #endregion
2550
2551    #region ohjaimet
2552
2553    /// <summary>
2554    /// Asetetaan ohjaimet.
2555    /// </summary>
2556    void AsetaOhjaimet()
2557    {
2558        // Pelaajan 1 ohjaimet
2559        Keyboard.Listen(Key.Escape, Jypeli.ButtonState.Pressed, LuoPauseValikko, "Lopeta peli");
2560        Keyboard.Listen(Key.W, Jypeli.ButtonState.Down, LiikutaPelaajaa, "", pelaajat[0], new Vector(0.0, 1.0));
2561        Keyboard.Listen(Key.S, Jypeli.ButtonState.Down, LiikutaPelaajaa, "", pelaajat[0], new Vector(0.0, -1.0));
2562        Keyboard.Listen(Key.A, Jypeli.ButtonState.Down, LiikutaPelaajaa, "", pelaajat[0], new Vector(-1.0, 0.0));
2563        Keyboard.Listen(Key.D, Jypeli.ButtonState.Down, LiikutaPelaajaa, "", pelaajat[0], new Vector(1.0, 0.0));
2564        Keyboard.Listen(Key.R, Jypeli.ButtonState.Pressed, delegate
2565        {
2566            lippaanPoistoAani.Play();
2567            pelaajat[0].LadataankoAsetta = true;
2568            if (pelaajat[0].ValittuAse.LatausAnimaatio1 != null)
2569            {
2570                pelaajat[0].Animation = new Animation(pelaajat[0].ValittuAse.LatausAnimaatio1);
2571                pelaajat[0].Animation.Start(1);
2572                pelaajat[0].Animation.FPS = pelaajat[0].Animation.FrameCount / pelaajat[0].ValittuAse.LataukseenKuluvaAika;
2573            }
2574            Timer.SingleShot(pelaajat[0].ValittuAse.LataukseenKuluvaAika, delegate { Lataa(pelaajat[0]); });
2575        }, null);
2576        Keyboard.Listen(Key.LeftShift, Jypeli.ButtonState.Pressed, delegate { pelaajat[0].Nopeus = 450.0; ;}, null);
2577        Keyboard.Listen(Key.LeftShift, Jypeli.ButtonState.Released, delegate { pelaajat[0].Nopeus = 300.0; ;}, null);
2578        Keyboard.Listen(Key.E, ButtonState.Pressed, MeleeIsku, null, pelaajat[0]);
2579        Mouse.ListenWheel(delegate { VaihdaAsetta(pelaajat[0]); }, null);
2580        Mouse.Listen(MouseButton.Left, Jypeli.ButtonState.Down, delegate
2581        {
2582            if (pelaajat[0].ValittuAse.BulletsPerShot != 1) AmmuHaulikolla(pelaajat[0], pelaajat[0].ValittuAse.BulletsPerShot);
2583            else Ammu(pelaajat[0]);
2584        }, null);
2585        Mouse.Listen(MouseButton.Right, Jypeli.ButtonState.Pressed, HeitaKranaatti, null, pelaajat[0]);
2586        Mouse.ListenMovement(0.1, LiikutaTahtainta, null, pelaajat[0]);
2587#if DEBUG
2588        Keyboard.Listen(Key.RightControl, ButtonState.Pressed, delegate { MessageDisplay.Add(pelaajat[0].Position.ToString()); }, null);
2589        Keyboard.Listen(Key.P, ButtonState.Pressed, delegate { MessageDisplay.Add(OnkoNaytonAlueella(new Vector(0.0, 0.0)).ToString()); }, null);
2590        Keyboard.Listen(Key.NumPad9, ButtonState.Pressed, delegate { Add(fysLaskuri); }, null);
2591        Keyboard.Listen(Key.O, ButtonState.Pressed, LuoHelikopteri, null, pelaajat[0].tahtain.Position);
2592#endif
2593
2594        // Pelaajan 2 ohjaimet
2595        ControllerOne.ListenAnalog(AnalogControl.LeftStick, 0.1, LiikutaPelaajaaPadilla, null, pelaajat[1]);
2596        ControllerOne.Listen(Button.LeftStick, Jypeli.ButtonState.Pressed, delegate { pelaajat[1].Nopeus = 450.0; }, null);
2597        ControllerOne.Listen(Button.LeftStick, Jypeli.ButtonState.Released, delegate { pelaajat[1].Nopeus = 300.0; }, null);
2598        ControllerOne.ListenAnalog(AnalogControl.RightStick, 0.1, LiikutaTahtaintaPadilla, null, pelaajat[1]);
2599        ControllerOne.Listen(Button.RightTrigger, Jypeli.ButtonState.Down, delegate
2600        {
2601            if (pelaajat[1].ValittuAse.BulletsPerShot != 1) AmmuHaulikolla(pelaajat[1], pelaajat[1].ValittuAse.BulletsPerShot);
2602            else Ammu(pelaajat[1]);
2603        }, null);
2604        ControllerOne.Listen(Button.LeftTrigger, Jypeli.ButtonState.Pressed, HeitaKranaatti, null, pelaajat[1]);
2605        ControllerOne.Listen(Button.LeftShoulder, Jypeli.ButtonState.Pressed, delegate { VaihdaAsetta(pelaajat[1], -1); }, null);
2606        ControllerOne.Listen(Button.RightShoulder, Jypeli.ButtonState.Pressed, delegate { VaihdaAsetta(pelaajat[1], 1); }, null);
2607        ControllerOne.Listen(Button.X, Jypeli.ButtonState.Pressed, delegate
2608        {
2609            lippaanPoistoAani.Play(); pelaajat[1].LadataankoAsetta = true;
2610            if (pelaajat[1].ValittuAse.LatausAnimaatio1 != null)
2611            {
2612                pelaajat[1].Animation = new Animation(pelaajat[1].ValittuAse.LatausAnimaatio2);
2613                pelaajat[1].Animation.Start(1);
2614                pelaajat[1].Animation.FPS = pelaajat[1].Animation.FrameCount / pelaajat[1].ValittuAse.LataukseenKuluvaAika;
2615            }
2616            Timer.SingleShot(pelaajat[1].ValittuAse.LataukseenKuluvaAika, delegate { Lataa(pelaajat[1]); });
2617        }, null);
2618        ControllerOne.Listen(Button.A, Jypeli.ButtonState.Pressed, delegate { pelaajat[1].tahtain.Position = pelaajat[1].Position; }, null);
2619        ControllerOne.Listen(Button.RightStick, ButtonState.Pressed, MeleeIsku, null, pelaajat[1]);
2620    }
2621
2622    /// <summary>
2623    /// Otetaan käyttöön sandbox-lisäohjaimet.
2624    /// </summary>
2625    void AsetaSandboxOhjaimet()
2626    {
2627        Keyboard.Listen(Key.Space, ButtonState.Pressed, delegate { LuoTuhoutuvaKentanOsa(SijoitaKentanosaRuudukkoon(pelaajat[0].tahtain.Position), 50, 50, null, kivenKuva, "kivi", 20, 1.0, 1.0); }, null);
2628        Keyboard.Listen(Key.K, ButtonState.Pressed, delegate { LuoKillBall(pelaajat[0].tahtain.Position); }, null);
2629        Keyboard.Listen(Key.T, ButtonState.Pressed, delegate { LuoTynnyri(SijoitaKentanosaRuudukkoon(pelaajat[0].tahtain.Position), 50.0, 50.0, null); }, null);
2630        Keyboard.Listen(Key.Delete, ButtonState.Pressed, RemoveAllEntities, null);
2631        Keyboard.Listen(Key.C, ButtonState.Down, delegate
2632        {
2633            Vihollinen zombi = new Vihollinen(normaaliZombiKuva.Width / 1.2, normaaliZombiKuva.Height / 1.2, normaaliZombiKuva, 20, 4, 100, pelaajat, false, false, this, null);
2634            Add(zombi);
2635            zombi.Position = pelaajat[0].tahtain.Position;
2636
2637        }, null);
2638        ControllerOne.Listen(Button.B, ButtonState.Pressed, delegate { LuoTuhoutuvaKentanOsa(SijoitaKentanosaRuudukkoon(pelaajat[1].tahtain.Position), 50, 50, null, kivenKuva, "kivi", 20, 1.0, 1.0); }, null);
2639        ControllerOne.Listen(Button.Y, ButtonState.Pressed, delegate { LuoTynnyri(SijoitaKentanosaRuudukkoon(pelaajat[1].tahtain.Position), 50.0, 50.0, null); }, null);
2640        ControllerOne.Listen(Button.DPadUp, ButtonState.Pressed, delegate
2641        {
2642            Vihollinen zombi = new Vihollinen(normaaliZombiKuva.Width / 1.2, normaaliZombiKuva.Height / 1.2, normaaliZombiKuva, 20, 4, 100, pelaajat, false, false, this, null);
2643            Add(zombi);
2644            zombi.Position = pelaajat[1].tahtain.Position;
2645
2646        }, null);
2647    }
2648
2649    #endregion
2650
2651    #region aseiden osumat
2652
2653    /// <summary>
2654    /// Kutsutaan, kun singon raketti osuu johonkin.
2655    /// </summary>
2656    /// <param name="ammus">Ammus, joka osuu.</param>
2657    /// <param name="kohde">Kohde, johon osutaan.</param>
2658    public void SingonAmmusRajahtaa(PhysicsObject ammus, PhysicsObject kohde)
2659    {
2660        Explosion sinkopaineaalto = new Explosion(200);
2661        sinkopaineaalto.Position = ammus.Position;
2662        sinkopaineaalto.Image = tyhjä;
2663        sinkopaineaalto.Sound = null;
2664        sinkopaineaalto.Force = 400;
2665        sinkopaineaalto.Speed = 1000;
2666        sinkopaineaalto.ShockwaveColor = Color.Black;
2667        sinkopaineaalto.ShockwaveReachesObject += delegate(IPhysicsObject paineaallonKohde, Vector shokki) { RajahdysOsuu(paineaallonKohde, shokki, ammus.Position, Aseet.SINGON_MAKSIMI_DAMAGE); };
2668
2669        Add(sinkopaineaalto);
2670        Aseet.singonAani.Play();
2671
2672        Partikkelit.AddParticleEffect(Partikkelit.RajahdysPartikkelit1, new Vector(kohde.X, kohde.Y), 500);
2673        Partikkelit.AddParticleEffect(Partikkelit.RajahdysPartikkelit2, new Vector(kohde.X, kohde.Y), 300);
2674        ammus.Destroy();
2675
2676        valo.Position = ammus.Position;
2677        valo.Intensity = 2.0;
2678        valo.Distance = 100;
2679        Timer.SingleShot(0.2, delegate { valo.Intensity = 1.5; });
2680        Timer.SingleShot(0.3, delegate { valo.Intensity = 1.0; });
2681        Timer.SingleShot(0.4, delegate { valo.Intensity = 0.5; });
2682        Timer.SingleShot(0.5, delegate { valo.Intensity = 0.0; });
2683    }
2684
2685    /// <summary>
2686    /// Lasketaan räjähdyksen aiheuttama vahinko etäisyyden mukaan.
2687    /// </summary>
2688    /// <param name="rajahdyksenKeskiPiste">Räjähdyksen keskipiste.</param>
2689    /// <param name="kohde">Kohde, johon räjähdys osuu.</param>
2690    /// <param name="maksimivahinko">Vahinko, jonka räjähdys tekee nollapisteessä.</param>
2691    /// <param name="nopeusJollaVahinkoVahenee">Nopeus, jolla räjähdyksen vahinko vähenee etäisyyden kasvaessa. Suurempi luku hidastaa, pienempi nopeuttaa.</param>
2692    /// <returns>Vahinko.</returns>
2693    double LaskeRajahdyksenDamage(Vector rajahdyksenKeskiPiste, Vector kohde, double maksimivahinko, double nopeusJollaVahinkoVahenee)
2694    {
2695        double pisteidenEtaisyys = Vector.Distance(rajahdyksenKeskiPiste, kohde) / nopeusJollaVahinkoVahenee;
2696        double damage = maksimivahinko - pisteidenEtaisyys;
2697        if (damage < 0) return 0;
2698        return damage;
2699    }
2700
2701    /// <summary>
2702    /// Törmäyksenkuuntelija räjähdyksille.
2703    /// </summary>
2704    /// <param name="kohde">Kohde, johon räjähdys osuu.</param>
2705    /// <param name="shokki">Pakollinen parametri.</param>
2706    void RajahdysOsuu(IPhysicsObject kohde, Vector shokki, Vector rajahdyksenAlkamisPiste, double maksimivahinko)
2707    {
2708        double todellinenVahinko = LaskeRajahdyksenDamage(rajahdyksenAlkamisPiste, kohde.Position, maksimivahinko, 8);
2709        if (todellinenVahinko == 0) return;
2710
2711        if (kohde is Tuhoutuva)
2712        {
2713            //Partikkelit.AddParticleEffect(Partikkelit.KiviHajoaa, new Vector(kohde.X, kohde.Y), 50);
2714            //Partikkelit.AddParticleEffect(Partikkelit.PuuHajoaa, new Vector(kohde.X, kohde.Y), 50);
2715            if (kohde != null) Damagea(kohde as Tuhoutuva, todellinenVahinko);
2716        }
2717
2718        if (kohde is Elava)
2719        {
2720            Elava kohdePelaaja = kohde as Elava;
2721            Partikkelit.AddParticleEffect(Partikkelit.VeriPartikkelit, new Vector(kohde.X, kohde.Y), 40);
2722            GameObject[] effects = Blood.AddNormalBlood(kohde.Position, 3, 0.3);
2723            foreach (GameObject blood in effects)
2724            {
2725                LisaaTehosteObjekti(blood);
2726            }
2727            Damagea(kohdePelaaja, todellinenVahinko);
2728        }
2729    }
2730    #endregion
2731}
Note: See TracBrowser for help on using the repository browser.