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

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