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

Revision 4580, 108.8 KB checked in by anlakane, 6 years ago (diff)

Talletus.

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