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

Revision 4734, 120.1 KB checked in by anlakane, 6 years ago (diff)

Bugikorjauksia ja viilauksia.

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