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

Revision 4640, 110.3 KB checked in by anlakane, 10 years ago (diff)

Laitettu Sandboxissa palikat menemään ruudukkoon. Lisätty helikopteri ja tehty siihen nousu ja lasku. Helikopteri kasvaa liikaa toisella nousulla.

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
1105    void LuoHelikopteri(Vector paikka)
1106    {
1107        Helikopteri kopteri = new Helikopteri(73, 233, 50, false); // 211, 171
1108        kopteri.Position = paikka;
1109        Add(kopteri, 2);
1110
1111#if DEBUG
1112        Keyboard.Listen(Key.I, ButtonState.Pressed, kopteri.NouseIlmaan, null);
1113        Keyboard.Listen(Key.U, ButtonState.Pressed, kopteri.AloitaLaskeutuminen, null);
1114#endif
1115    }
1116
1117    /// <summary>
1118    /// Asetetaan pelaajan lisäämät seinät siten, että se eivät mene sisäkkäin.
1119    /// </summary>
1120    /// <param name="realPos">Paikka, johon seinää yritetään lisätä.</param>
1121    void SijoitaKentanosaRuudukkoon(Vector mousePos)
1122    {
1123        int merkki = Math.Sign(mousePos.X);
1124        double x = mousePos.X - mousePos.X % Vakiot.KENTAN_RUUDUN_LEVEYS + merkki * Vakiot.KENTAN_RUUDUN_LEVEYS / 2;
1125        merkki = Math.Sign(mousePos.Y);
1126        double y = mousePos.Y - (mousePos.Y % Vakiot.KENTAN_RUUDUN_KORKEUS) + merkki * Vakiot.KENTAN_RUUDUN_KORKEUS / 2;
1127
1128        Vector posRuudukossa = new Vector(x, y);
1129
1130        LuoTuhoutuvaKentanOsa(posRuudukossa, 50, 50, null, kivenKuva, "kivi", 20, 1.0, 1.0);
1131    }
1132
1133    #endregion
1134
1135    #endregion
1136
1137    #region valikot
1138    /// <summary>
1139    /// Luodaan pelille alkuvalikko.
1140    /// </summary>
1141    /// <param name="isEverythingCleared">Jos kutsutaan ClearAllin jälkeen.</param>
1142    void LuoAlkuValikko(bool isEverythingCleared = false)
1143    {
1144        MW2_My_Warfare_2_.Peli = this;
1145        AsetustenKaytto.LataaAsetukset();
1146        Infinite.OnkoPeliKaynnissa = false;
1147        AnimatedMultiSelectWindow valikko = new AnimatedMultiSelectWindow("MY WARFARE 2", valikonPainikeKuva,
1148        "Uusi peli", "Multiplayer", "Asetukset", "Lopeta peli");
1149        valikko.ItemSelected += PainettiinAlkuValikonNappia;
1150        valikko.Color = Color.Transparent;
1151        valikko.BorderColor = Color.Transparent;
1152        valikko.MovementSpeed = 450;
1153        Level.Background.Image = valikonKuva;
1154        Level.BackgroundColor = Color.Black;
1155        Level.AmbientLight = 1.0;
1156        valikko.DefaultCancel = 4;
1157        Partikkelit.LisaaValikkoTaustaPartikkelit();
1158        Add(valikko);
1159
1160        if (menuGradient == null || menuGradient.IsDestroyed || !menuGradient.IsAddedToGame || isEverythingCleared) // jos null tai poistettu pelistä tai jos tullaan ClearAllin kautta
1161        {
1162            menuGradient = new GameObject(1920, 1080);
1163            menuGradient.Image = LoadImage("menu_gradient");
1164            Add(menuGradient);
1165        }
1166    }
1167
1168    /// <summary>
1169    /// Alkuvalikon nappien painalluksen käsittely.
1170    /// </summary>
1171    /// <param name="valinta">Painettu nappi.</param>
1172    void PainettiinAlkuValikonNappia(int valinta)
1173    {
1174        switch (valinta)
1175        {
1176            case 0:
1177                LuoPelimuodonValintaValikko();
1178                break;
1179            case 1:
1180                LuoOnlineValikko();
1181                break;
1182            case 2:
1183                LuoAsetusIkkuna();
1184                break;
1185            case 3:
1186                Exit();
1187                break;
1188        }
1189    }
1190
1191    void LuoOnlineValikko()
1192    {
1193        AnimatedMultiSelectWindow onlineValikko = new AnimatedMultiSelectWindow("Valitse pelimuoto", valikonPainikeKuva, "Liity peliin", "Syötä IP", "Syötä portti", "Syötä salasana", "Takaisin");
1194        onlineValikko.ItemSelected += PainettiinOnlineValikonNappia;
1195        onlineValikko.Color = Color.Transparent;
1196        onlineValikko.BorderColor = Color.Transparent;
1197        Level.Background.Image = valikonKuva;
1198        Level.BackgroundColor = Color.Black;
1199        onlineValikko.DefaultCancel = 2;
1200        //onlineValikko.Position = new Vector(0, Screen.Top - 100);
1201        Add(onlineValikko);
1202
1203    }
1204
1205    void PainettiinOnlineValikonNappia(int valinta)
1206    {
1207        switch (valinta)
1208        {
1209            case 0:
1210                OnlineGame.JoinGame(new System.Net.IPEndPoint(System.Net.IPAddress.Parse(OnlineGame.ServerIP.ToString()), OnlineGame.ServerPort));
1211                LuoOnlineKentta(OnlineGame.CurrentGame.ConnectedPlayers, 2);
1212
1213                break;
1214            case 1:
1215                InputWindow ipIkkuna = new InputWindow("Syötä serverin IP:");
1216                ipIkkuna.Color = Color.Transparent;
1217                ipIkkuna.InputBox.BorderColor = Color.Green;
1218                ipIkkuna.InputBox.Cursor.Color = Color.Green;
1219                ipIkkuna.MaxCharacters = 15;
1220                ipIkkuna.OKButton.Clicked += delegate
1221                {
1222                    OnlineGame.ServerIP.Clear();
1223                    OnlineGame.ServerIP.Append(ipIkkuna.InputBox.Text);
1224                    LuoOnlineValikko();
1225                };
1226                Add(ipIkkuna);
1227                break;
1228            case 2:
1229                InputWindow porttiIkkuna = new InputWindow("Syötä serverin portti:");
1230                porttiIkkuna.Color = Color.Transparent;
1231                porttiIkkuna.InputBox.BorderColor = Color.Green;
1232                porttiIkkuna.InputBox.Cursor.Color = Color.Green;
1233                porttiIkkuna.MaxCharacters = 5;
1234                porttiIkkuna.OKButton.Clicked += delegate
1235                {
1236                    OnlineGame.ServerPort = int.Parse(porttiIkkuna.InputBox.Text);
1237                    LuoOnlineValikko();
1238                };
1239                Add(porttiIkkuna);
1240
1241                break;
1242            case 3:
1243                InputWindow salasanaIkkuna = new InputWindow("Syötä serverin portti:");
1244                salasanaIkkuna.Color = Color.Transparent;
1245                salasanaIkkuna.InputBox.BorderColor = Color.Green;
1246                salasanaIkkuna.InputBox.Cursor.Color = Color.Green;
1247                salasanaIkkuna.OKButton.Clicked += delegate
1248                {
1249                    OnlineGame.ServerPassword.Clear();
1250                    OnlineGame.ServerPassword.Append(salasanaIkkuna.InputBox.Text);
1251                    LuoOnlineValikko();
1252                };
1253                Add(salasanaIkkuna);
1254                break;
1255            case 4:
1256                LuoAlkuValikko();
1257                break;
1258        }
1259    }
1260
1261    /// <summary>
1262    /// Asetukset, kuten fullscreen-valinta, antialiasing ja resoluutio.
1263    /// </summary>
1264    void LuoAsetusIkkuna()
1265    {
1266        AsetustenKaytto.LataaAsetukset();
1267        Mouse.IsCursorVisible = true;
1268        MultiSelectWindow paluu = new MultiSelectWindow("Asetukset", "Tallenna ja palaa päävalikkoon", "Palauta oletusasetukset");
1269        paluu.ItemSelected += delegate(int valinta)
1270        {
1271            switch (valinta)
1272            {
1273                case 0:
1274                    AsetustenKaytto.TallennaAsetukset();
1275                    PaaValikkoon();
1276                    break;
1277                case 1:
1278                    AsetustenKaytto.PalautaOletusAsetukset();
1279                    AsetustenKaytto.TallennaAsetukset();
1280                    PaaValikkoon();
1281                    break;
1282            }
1283        };
1284        paluu.Color = Color.Transparent;
1285        paluu.BorderColor = Color.Transparent;
1286        paluu.SelectionColor = Color.Green;
1287        Level.Background.Image = valikonKuva;
1288        Level.BackgroundColor = Color.Black;
1289        paluu.DefaultCancel = 0;
1290        paluu.Position = new Vector(0, Screen.Top - 100);
1291        Add(paluu);
1292
1293        OnOffButton fullscreenNappi = new OnOffButton(20, 20, AsetustenKaytto.Asetukset.OnkoFullscreen);
1294        fullscreenNappi.Position = new Vector(0.0, paluu.Y - 100);
1295        Add(fullscreenNappi);
1296        fullscreenNappi.Clicked += delegate { AsetustenKaytto.Asetukset.OnkoFullscreen = fullscreenNappi.IsPressed; this.IsFullScreen = AsetustenKaytto.Asetukset.OnkoFullscreen; };
1297
1298        Label fullscreenTeksti = new Label("Fullscreen:");
1299        fullscreenTeksti.Position = new Vector(fullscreenNappi.X - 100, fullscreenNappi.Y);
1300        Add(fullscreenTeksti);
1301
1302        OnOffButton antialiasingNappi = new OnOffButton(20, 20, AsetustenKaytto.Asetukset.OnkoAntialiasing);
1303        antialiasingNappi.Position = new Vector(0.0, fullscreenNappi.Y - 50);
1304        Add(antialiasingNappi);
1305        antialiasingNappi.Clicked += delegate { AsetustenKaytto.Asetukset.OnkoAntialiasing = antialiasingNappi.IsPressed; Game.SmoothTextures = AsetustenKaytto.Asetukset.OnkoAntialiasing; };
1306
1307        Label antialiasingTeksti = new Label("Antialiasing:");
1308        antialiasingTeksti.Position = new Vector(antialiasingNappi.X - 100, antialiasingNappi.Y);
1309        Add(antialiasingTeksti);
1310
1311        Label resoluutiotOtsikko = new Label("Resoluutio:");
1312        resoluutiotOtsikko.Position = new Vector(antialiasingTeksti.X, antialiasingTeksti.Y - 50);
1313        Add(resoluutiotOtsikko);
1314
1315        PushButton resoluutio800x600 = new PushButton(20, 20);
1316        resoluutio800x600.Position = new Vector(100.0, resoluutiotOtsikko.Y - 50);
1317        Add(resoluutio800x600);
1318        resoluutio800x600.Clicked += delegate { AsetaIkkunanKoko(800, 600); };
1319
1320        Label resoluutio800x600Teksti = new Label("800 x 600");
1321        resoluutio800x600Teksti.Position = new Vector(resoluutio800x600.X - 100, resoluutio800x600.Y);
1322        Add(resoluutio800x600Teksti);
1323
1324        PushButton resoluutio1024x768 = new PushButton(20, 20);
1325        resoluutio1024x768.Position = new Vector(100.0, resoluutio800x600.Y - 50);
1326        Add(resoluutio1024x768);
1327        resoluutio1024x768.Clicked += delegate { AsetaIkkunanKoko(1024, 768); };
1328
1329        Label resoluutio1024x768Teksti = new Label("1024 x 768");
1330        resoluutio1024x768Teksti.Position = new Vector(resoluutio1024x768.X - 100, resoluutio1024x768.Y);
1331        Add(resoluutio1024x768Teksti);
1332
1333        PushButton resoluutio1280x1024 = new PushButton(20, 20);
1334        resoluutio1280x1024.Position = new Vector(100.0, resoluutio1024x768.Y - 50);
1335        Add(resoluutio1280x1024);
1336        resoluutio1280x1024.Clicked += delegate { AsetaIkkunanKoko(1280, 1024); };
1337
1338        Label resoluutio1280x1024Teksti = new Label("1280 x 1024");
1339        resoluutio1280x1024Teksti.Position = new Vector(resoluutio1280x1024.X - 100, resoluutio1280x1024.Y);
1340        Add(resoluutio1280x1024Teksti);
1341
1342        PushButton resoluutio1600x1200 = new PushButton(20, 20);
1343        resoluutio1600x1200.Position = new Vector(100.0, resoluutio1280x1024.Y - 50);
1344        Add(resoluutio1600x1200);
1345        resoluutio1600x1200.Clicked += delegate { AsetaIkkunanKoko(1600, 1200); };
1346
1347        Label resoluutio1600x1200Teksti = new Label("1600 x 1200");
1348        resoluutio1600x1200Teksti.Position = new Vector(resoluutio1600x1200.X - 100, resoluutio1600x1200.Y);
1349        Add(resoluutio1600x1200Teksti);
1350
1351        PushButton resoluutio1920x1080 = new PushButton(20, 20);
1352        resoluutio1920x1080.Position = new Vector(100.0, resoluutio1600x1200.Y - 50);
1353        Add(resoluutio1920x1080);
1354        resoluutio1920x1080.Clicked += delegate { AsetaIkkunanKoko(1920, 1080); };
1355
1356        Label resoluutio1920x1080Teksti = new Label("1920 x 1080");
1357        resoluutio1920x1080Teksti.Position = new Vector(resoluutio1920x1080.X - 100, resoluutio1920x1080.Y);
1358        Add(resoluutio1920x1080Teksti);
1359
1360        OnOffButton pelaaja1LaserNappi = new OnOffButton(20, 20, AsetustenKaytto.Asetukset.OnkoPelaajalla1Lasertahtainta);
1361        pelaaja1LaserNappi.Position = new Vector(0.0, resoluutio1920x1080.Y - 50);
1362        Add(pelaaja1LaserNappi);
1363        pelaaja1LaserNappi.Clicked += delegate { AsetustenKaytto.Asetukset.OnkoPelaajalla1Lasertahtainta = !AsetustenKaytto.Asetukset.OnkoPelaajalla1Lasertahtainta; };
1364
1365        Label pelaaja1LaserTeksti = new Label("Pelaajan 1 lasertähtäin:");
1366        pelaaja1LaserTeksti.Position = new Vector(pelaaja1LaserNappi.X - 150, pelaaja1LaserNappi.Y);
1367        Add(pelaaja1LaserTeksti);
1368
1369        OnOffButton pelaaja2LaserNappi = new OnOffButton(20, 20, AsetustenKaytto.Asetukset.OnkoPelaajalla2Lasertahtainta);
1370        pelaaja2LaserNappi.Position = new Vector(0.0, pelaaja1LaserNappi.Y - 50);
1371        Add(pelaaja2LaserNappi);
1372        pelaaja2LaserNappi.Clicked += delegate { AsetustenKaytto.Asetukset.OnkoPelaajalla2Lasertahtainta = !AsetustenKaytto.Asetukset.OnkoPelaajalla2Lasertahtainta; };
1373
1374        Label pelaaja2LaserTeksti = new Label("Pelaajan 2 lasertähtäin:");
1375        pelaaja2LaserTeksti.Position = new Vector(pelaaja2LaserNappi.X - 150, pelaaja2LaserNappi.Y);
1376        Add(pelaaja2LaserTeksti);
1377
1378        PushButton kayttajaNimiNappi = new PushButton("Muuta");
1379        kayttajaNimiNappi.Color = Color.Green;
1380        kayttajaNimiNappi.Position = new Vector(0.0, pelaaja2LaserNappi.Position.Y - 50);
1381        kayttajaNimiNappi.Clicked += delegate
1382        {
1383            InputWindow kayttajanimiIkkuna = new InputWindow("");
1384            kayttajanimiIkkuna.Color = Color.Transparent;
1385            kayttajanimiIkkuna.InputBox.BorderColor = Color.Green;
1386            kayttajanimiIkkuna.InputBox.Text = AsetustenKaytto.Asetukset.KayttajaNimi;
1387            kayttajanimiIkkuna.InputBox.Cursor.Color = Color.Green;
1388            kayttajanimiIkkuna.Position = new Vector(0.0, kayttajaNimiNappi.Y - 50);
1389            kayttajanimiIkkuna.OKButton.Color = Color.Green;
1390            kayttajanimiIkkuna.OKButton.Clicked += delegate
1391            {
1392                AsetustenKaytto.Asetukset.KayttajaNimi = kayttajanimiIkkuna.InputBox.Text;
1393                AsetustenKaytto.TallennaAsetukset();
1394                LuoAsetusIkkuna();
1395            };
1396            Add(kayttajanimiIkkuna);
1397        };
1398        Add(kayttajaNimiNappi);
1399
1400        Label kayttajanimiTeksti = new Label("Käyttäjänimi: ");
1401        kayttajanimiTeksti.Position = new Vector(kayttajaNimiNappi.X - 150, kayttajaNimiNappi.Y);
1402        Add(kayttajanimiTeksti);
1403    }
1404
1405    /// <summary>
1406    /// Pelimuotovalikon luonti.
1407    /// </summary>
1408    void LuoPelimuodonValintaValikko()
1409    {
1410        AnimatedMultiSelectWindow pelimuotoValikko = new AnimatedMultiSelectWindow("Valitse pelimuoto", valikonPainikeKuva, "Deathmatch", "Infinite", "Sandbox", "Takaisin");
1411        pelimuotoValikko.ItemSelected += PainettiinPelimuotoValikonNappia;
1412        pelimuotoValikko.Color = Color.Transparent;
1413        pelimuotoValikko.BorderColor = Color.Transparent;
1414        Level.Background.Image = valikonKuva;
1415        Level.BackgroundColor = Color.Black;
1416        pelimuotoValikko.DefaultCancel = 2;
1417        Add(pelimuotoValikko);
1418    }
1419
1420    /// <summary>
1421    /// Pelimuotovalikon nappien painalluksen käsittely.
1422    /// </summary>
1423    /// <param name="valinta">Painettu nappi.</param>
1424    void PainettiinPelimuotoValikonNappia(int valinta)
1425    {
1426        switch (valinta)
1427        {
1428            case 0:
1429                LuoPelinKustomointiIkkuna();
1430                break;
1431            case 1:
1432                LuoInfinitevalikko();
1433                break;
1434            case 2:
1435                Level.Background.Image = null;
1436                ValittuKenttaTiedosto = "kenttä2"; // turha
1437                LuoKentta(2, 2, false);
1438                OnkoSatunnaisKentta = false;
1439                ClearControls();
1440                AsetaOhjaimet();
1441                AsetaSandboxOhjaimet();
1442                SoitaMusiikkia(3); // Sandbox: vanha OrcsCome
1443                Partikkelit.PoistaValikkoTaustaPartikkelit();
1444                break;
1445            case 3:
1446                LuoAlkuValikko();
1447                break;
1448        }
1449    }
1450
1451    /// <summary>
1452    /// Pelin kustomointi-ikkunan luonti.
1453    /// </summary>
1454    void LuoPelinKustomointiIkkuna()
1455    {
1456        List<Widget> ikkunanKomponentit = new List<Widget>();
1457
1458        MultiSelectWindow valikko = new MultiSelectWindow("Pelin kustomointi", "Klassinen mäppi", "Satunnaisgeneroitu mäppi", "Takaisin");
1459        valikko.ItemSelected += delegate(int valinta) { PainettiinPelinKustomointiIkkunanNappia(valinta, ikkunanKomponentit); };
1460        valikko.Color = Color.Transparent;
1461        valikko.SelectionColor = Color.Green;
1462        valikko.BorderColor = Color.Transparent;
1463        Level.Background.Image = valikonKuva;
1464        Level.BackgroundColor = Color.Black;
1465        valikko.DefaultCancel = 2;
1466        valikko.Position = new Vector(0.0, Screen.Top - valikko.Height);
1467        Add(valikko);
1468
1469        MonestakoVoittaa = new IntMeter(5, 1, 100);
1470
1471        Slider tapotJoillaVoittaa = new Slider(300.0, 20.0);
1472        tapotJoillaVoittaa.Position = new Vector(valikko.X, valikko.Y - 200);
1473        Add(tapotJoillaVoittaa);
1474        tapotJoillaVoittaa.BorderColor = Color.Transparent;
1475        tapotJoillaVoittaa.Color = Color.Transparent;
1476        tapotJoillaVoittaa.Knob.Color = Color.Green;
1477        tapotJoillaVoittaa.Track.Color = Color.DarkGreen;
1478        tapotJoillaVoittaa.BindTo(MonestakoVoittaa);
1479        ikkunanKomponentit.Add(tapotJoillaVoittaa);
1480
1481        Label tapotJoillaVoittaaOtsikko = new Label("Tappoja voittoon:");
1482        tapotJoillaVoittaaOtsikko.Position = new Vector(tapotJoillaVoittaa.X - tapotJoillaVoittaa.Width, tapotJoillaVoittaa.Y);
1483        Add(tapotJoillaVoittaaOtsikko);
1484        ikkunanKomponentit.Add(tapotJoillaVoittaaOtsikko);
1485
1486        Label tapotJoillaVoittaaNaytto = new Label();
1487        tapotJoillaVoittaaNaytto.BindTo(MonestakoVoittaa);
1488        tapotJoillaVoittaaNaytto.Position = new Vector(tapotJoillaVoittaa.X + tapotJoillaVoittaa.Width / 1.5, tapotJoillaVoittaa.Y);
1489        Add(tapotJoillaVoittaaNaytto);
1490        ikkunanKomponentit.Add(tapotJoillaVoittaaNaytto);
1491    }
1492
1493    /// <summary>
1494    /// Handleri pelin kustomointinäytön napeille.
1495    /// </summary>
1496    /// <param name="valinta">Valittu nappi.</param>
1497    /// <param name="poistettavatIkkunanKomponentit">Mitkä kaikki poistetaan, kun nappia painetaan.</param>
1498    void PainettiinPelinKustomointiIkkunanNappia(int valinta, List<Widget> poistettavatIkkunanKomponentit)
1499    {
1500        foreach (Widget ikkunanKomponentti in poistettavatIkkunanKomponentit)
1501        {
1502            ikkunanKomponentti.Destroy();
1503        }
1504
1505
1506
1507        switch (valinta)
1508        {
1509            case 0:
1510                Level.Background.Image = null;
1511                ValittuKenttaTiedosto = "kenttä2"; // kenttä2
1512                LuoKentta(0, 2, false);
1513                ClearControls();
1514                AsetaOhjaimet();
1515                SoitaMusiikkia(1); // DarkLurk deathmatchiin
1516                //Level.Background.Image = LoadImage("Pohja_testi");
1517                Partikkelit.PoistaValikkoTaustaPartikkelit();
1518                break;
1519            case 1:
1520                Level.Background.Image = null;
1521                ValittuKenttaTiedosto = "kenttä2";
1522                LuoKentta(1, 2, false);
1523                OnkoSatunnaisKentta = true;
1524                ClearControls();
1525                AsetaOhjaimet();
1526                SoitaMusiikkia(1); // DarkLurk deathmatchiin
1527                Partikkelit.PoistaValikkoTaustaPartikkelit();
1528                break;
1529            case 2:
1530                LuoPelimuodonValintaValikko();
1531                break;
1532        }
1533    }
1534
1535    /// <summary>
1536    /// Infinitevalikon luonti.
1537    /// </summary>
1538    void LuoInfinitevalikko()
1539    {
1540        List<Widget> ikkunanKomponentit = new List<Widget>();
1541        IntMeter monestakoHaviaa = new IntMeter(1, 0, 100);
1542        Level.Background.Image = null;
1543        MultiSelectWindow infinitevalikko = new MultiSelectWindow("Valitse pelaajien määrä", "Yksinpeli", "Moninpeli", "Takaisin");
1544        infinitevalikko.ItemSelected += delegate(int valinta) { PainettiinInfiniteMenunNappia(valinta, monestakoHaviaa.Value, ikkunanKomponentit); };
1545        infinitevalikko.Color = Color.Transparent;
1546        infinitevalikko.SelectionColor = Color.Green;
1547        infinitevalikko.BorderColor = Color.Transparent;
1548        infinitevalikko.Position = new Vector(0.0, Screen.Top - infinitevalikko.Height);
1549        Level.Background.Image = valikonKuva;
1550        infinitevalikko.DefaultCancel = 2;
1551        Add(infinitevalikko);
1552
1553        Slider kuolematJoillaHaviaa = new Slider(300.0, 20.0);
1554        kuolematJoillaHaviaa.Position = new Vector(infinitevalikko.X, infinitevalikko.Y - 200);
1555        Add(kuolematJoillaHaviaa);
1556        kuolematJoillaHaviaa.BorderColor = Color.Transparent;
1557        kuolematJoillaHaviaa.Color = Color.Transparent;
1558        kuolematJoillaHaviaa.Knob.Color = Color.Green;
1559        kuolematJoillaHaviaa.Track.Color = Color.DarkGreen;
1560        kuolematJoillaHaviaa.BindTo(monestakoHaviaa);
1561        ikkunanKomponentit.Add(kuolematJoillaHaviaa);
1562
1563        Label kuolematJoillaHaviaaOtsikko = new Label("Respauksia käytössä:");
1564        kuolematJoillaHaviaaOtsikko.Position = new Vector(kuolematJoillaHaviaa.X - kuolematJoillaHaviaa.Width, kuolematJoillaHaviaa.Y);
1565        Add(kuolematJoillaHaviaaOtsikko);
1566        ikkunanKomponentit.Add(kuolematJoillaHaviaaOtsikko);
1567
1568        Label kuolematJoillaHaviaaNaytto = new Label();
1569        kuolematJoillaHaviaaNaytto.BindTo(monestakoHaviaa);
1570        kuolematJoillaHaviaaNaytto.Position = new Vector(kuolematJoillaHaviaa.X + kuolematJoillaHaviaa.Width / 1.5, kuolematJoillaHaviaa.Y);
1571        Add(kuolematJoillaHaviaaNaytto);
1572        ikkunanKomponentit.Add(kuolematJoillaHaviaaNaytto);
1573
1574    }
1575
1576    /// <summary>
1577    /// Infinitevalikon napin painalluksen käsittely.
1578    /// </summary>
1579    /// <param name="valinta">Mitä painettiin.</param>
1580    /// <param name="monestakoPoikki">Monestako peli menee poikki.</param>
1581    /// <param name="poistettavatJutut">Pitä poistetaan, kun nappia painetaan.</param>
1582    void PainettiinInfiniteMenunNappia(int valinta, int monestakoPoikki, List<Widget> poistettavatJutut)
1583    {
1584        foreach (Widget poistettava in poistettavatJutut)
1585        {
1586            poistettava.Destroy();
1587        }
1588
1589        switch (valinta)
1590        {
1591            case 0: // Infiniten yksinpeli
1592                Level.Background.Image = null;
1593                ValittuKenttaTiedosto = "Minium"; // zombimäppi1
1594                ClearControls();
1595                SoitaMusiikkia(4); // OrcsCome Special
1596                AloitaInfiniteGame(1, 0, monestakoPoikki);
1597                AsetaOhjaimet();
1598                Partikkelit.PoistaValikkoTaustaPartikkelit();
1599                break;
1600
1601            case 1: // Infiniten kaksinpeli
1602                Level.Background.Image = null;
1603                ValittuKenttaTiedosto = "Minium";
1604                ClearControls();
1605                SoitaMusiikkia(4); // OrcsCome Special
1606                AloitaInfiniteGame(2, 0, monestakoPoikki);
1607                AsetaOhjaimet();
1608                Partikkelit.PoistaValikkoTaustaPartikkelit();
1609                break;
1610            case 2:
1611                LuoPelimuodonValintaValikko();
1612                break;
1613        }
1614    }
1615
1616    /// <summary>
1617    /// Luodaan pausevalikko.
1618    /// </summary>
1619    void LuoPauseValikko()
1620    {
1621        IsPaused = true;
1622        MultiSelectWindow valikko = new MultiSelectWindow("TAUKO", "Takaisin peliin", "Päävalikkoon", "Poistu pelistä");
1623        valikko.ItemSelected += PainettiinPauseValikonNappia;
1624        valikko.Color = Color.Transparent;
1625        valikko.BorderColor = Color.Transparent;
1626        valikko.SelectionColor = Color.Green;
1627        valikko.DefaultCancel = 0;
1628        Add(valikko);
1629    }
1630
1631    /// <summary>
1632    /// Pausevalikon nappien painalluksen käsittely.
1633    /// </summary>
1634    /// <param name="valinta">Painettu nappi.</param>
1635    void PainettiinPauseValikonNappia(int valinta)
1636    {
1637        switch (valinta)
1638        {
1639            case 0:
1640                IsPaused = false;
1641                break;
1642            case 1:
1643                IsPaused = false;
1644                PaaValikkoon();
1645                break;
1646            case 2:
1647                Exit();
1648                break;
1649        }
1650    }
1651
1652    #endregion
1653
1654    #region infinite
1655
1656    /// <summary>
1657    /// Aloitetaan uusi Infinite-peli.
1658    /// </summary>
1659    /// <param name="pelaajienMaara">Montako pelaajaa peliin tulee.</param>
1660    /// <param name="kenttaTyyppi">Millaista kenttää käytetään.</param>
1661    /// <param name="monestakoRespauksestaPoikki">Monestako respauksesta peli menee poikki.-</param>
1662    void AloitaInfiniteGame(int pelaajienMaara, int kenttaTyyppi, int monestakoRespauksestaPoikki)
1663    {
1664        Infinite infinite = new Infinite(monestakoRespauksestaPoikki);
1665        LuoKentta(kenttaTyyppi, pelaajienMaara, true);
1666        LuoVihollistenMallineet(infinite);
1667        infinite.PeliPaattyi += InfiniteHavio;
1668        infinite.VihollistenSpawnausAjastin.Timeout += delegate { SpawnaaInfinitenVihollisia(infinite); };
1669        foreach (Pelaaja p in pelaajat)
1670        {
1671            p.Kuoli += infinite.PelaajaKuoli;
1672        }
1673
1674        if (kenttaTyyppi == 0)
1675        {
1676            infinite.KaytetaankoFixedSpawneja = true;
1677            //AsetaFixedSpawnitInfiniteen(infinite);
1678        }
1679        Level.AmbientLight = 0.4;
1680        if (pelaajienMaara == 1) Level.AmbientLight = 0.7; // koska taskulamppu
1681    }
1682
1683    /// <summary>
1684    /// Luodaan Infinitessä käytettävien vihollisten mallineet
1685    /// ja annetaan ne Infinite-pelimuodon spawnauslistaan.
1686    /// </summary>
1687    /// <param name="peli">Peli, johon viholliset lisätään.</param>
1688    void LuoVihollistenMallineet(Infinite peli)
1689    {
1690        // Tavallinen zombi
1691        Vihollinen zombi = new Vihollinen(normaaliZombiKuva.Width / 1.2, normaaliZombiKuva.Height / 1.2, normaaliZombiKuva, 20, 12, 100, pelaajat, false, false, this, peli); // nopeus oli 4
1692        peli.LisaaVihollinenPeliin(zombi);
1693
1694        // Zombi, jolla on ase
1695        /*Vihollinen ampuvaZombi = new Vihollinen(ampuvaZombiKuva.Width / 1.2, ampuvaZombiKuva.Height / 1.2, ampuvaZombiKuva, 20, 4, 100, pelaajat, true, false, this, peli);
1696        ampuvaZombi.AmpumisTarkkuus = 6.0;
1697        ampuvaZombi.EtaisyysJoltaAmpuu = 300.0;
1698        ampuvaZombi.ValittuAse = Aseet.LuoRynkky();
1699        ampuvaZombi.ValittuAse.AanenVoimakkuus = 0.5;
1700        ampuvaZombi.TodennakoisyysSpawnata = 0.3;
1701        peli.LisaaVihollinenPeliin(ampuvaZombi);*/
1702
1703        // Itsetuhoinen parasiitti
1704        /*Vihollinen parasiitti = new Vihollinen(10, 10, RandomGen.SelectOne<Image>(parasiittienKuvat), 1, 2, 200, pelaajat, false, true, this);
1705        parasiitti.KuolemaEfektinPartikkeliKuva = RandomGen.SelectOne<Image>(parasiittienPartikkeliKuvat);
1706        peli.LisaaVihollinenPeliin(parasiitti); */
1707    }
1708
1709    /// <summary>
1710    /// Spawnataan viholliset Infiniten spawnauslistasta.
1711    /// </summary>
1712    /// <param name="peli">Peli, jonka spawnauslistasta viholliset spawnataan.</param>
1713    void SpawnaaInfinitenVihollisia(Infinite peli)
1714    {
1715        foreach (Vihollinen vihu in peli.TallaSpawnauskerrallaSpawnattavatViholliset)
1716        {
1717            vihu.Destroyed += delegate { peli.VihollisiaTapettu.Value++; };
1718            Add(vihu);
1719            Vector paikka;
1720            if (peli.KaytetaankoFixedSpawneja && peli.VihollistenFixedSpawnit.Count != 0)
1721            {
1722                do
1723                {
1724                    paikka = RandomGen.SelectOne<Vector>(peli.VihollistenFixedSpawnit);
1725                } while (!OnkoNaytonAlueella(paikka));
1726                vihu.Position = paikka;
1727            }
1728            else vihu.Position = ArvoSpawnausPaikkaKentanLaidoilta(Vakiot.PALJONKO_VIHOLLISET_SPAWNAAVAT_KENTAN_RAJOJEN_ULKOPUOLELLE);
1729
1730            peli.VihollisetKentalla.Add(vihu);
1731        }
1732    }
1733
1734    /// <summary>
1735    /// Arvotaan satunnainen paikka kentän rajojen ulkopuolelta.
1736    /// </summary>
1737    /// <param name="paljonkoLaitojenUlkopuolelle">Paljonko paikka tulee kentän rajojen ulkopuolelle.</param>
1738    /// <returns>Satunnainen paikka kentän laidoilta.</returns>
1739    Vector ArvoSpawnausPaikkaKentanLaidoilta(double paljonkoLaitojenUlkopuolelle)
1740    {
1741        //Arvotaan satunnainen vektori kentän joka laidalle, ja arvotaan joku niistä
1742        Vector[] vaihtoehdot = new Vector[4];
1743        vaihtoehdot[0] = RandomGen.NextVector(Vakiot.PELAAJAN_PIENIN_SALLITTU_X_KENTALLA - paljonkoLaitojenUlkopuolelle, Vakiot.PELAAJAN_PIENIN_SALLITTU_Y_KENTALLA,
1744            Vakiot.PELAAJAN_PIENIN_SALLITTU_X_KENTALLA - paljonkoLaitojenUlkopuolelle, Vakiot.PELAAJAN_SUURIN_SALLITTU_Y_KENTALLA); // vasen reuna
1745
1746        vaihtoehdot[1] = RandomGen.NextVector(Vakiot.PELAAJAN_PIENIN_SALLITTU_X_KENTALLA, Vakiot.PELAAJAN_SUURIN_SALLITTU_Y_KENTALLA + paljonkoLaitojenUlkopuolelle,
1747            Vakiot.PELAAJAN_SUURIN_SALLITTU_X_KENTALLA, Vakiot.PELAAJAN_SUURIN_SALLITTU_Y_KENTALLA + paljonkoLaitojenUlkopuolelle); // yläreuna
1748
1749        vaihtoehdot[2] = RandomGen.NextVector(Vakiot.PELAAJAN_SUURIN_SALLITTU_X_KENTALLA + paljonkoLaitojenUlkopuolelle, Vakiot.PELAAJAN_PIENIN_SALLITTU_Y_KENTALLA,
1750            Vakiot.PELAAJAN_SUURIN_SALLITTU_X_KENTALLA + paljonkoLaitojenUlkopuolelle, Vakiot.PELAAJAN_SUURIN_SALLITTU_Y_KENTALLA); // oikea reuna
1751
1752        vaihtoehdot[3] = RandomGen.NextVector(Vakiot.PELAAJAN_PIENIN_SALLITTU_X_KENTALLA, Vakiot.PELAAJAN_PIENIN_SALLITTU_Y_KENTALLA - paljonkoLaitojenUlkopuolelle,
1753            Vakiot.PELAAJAN_SUURIN_SALLITTU_X_KENTALLA, Vakiot.PELAAJAN_PIENIN_SALLITTU_Y_KENTALLA - paljonkoLaitojenUlkopuolelle); // alareuna
1754        return RandomGen.SelectOne<Vector>(vaihtoehdot); // palautetaan yksi neljästä
1755    }
1756
1757    /// <summary>
1758    /// Asetetaan Infiniten fixed-spawnit normimäppiä varten.
1759    /// </summary>
1760    /// <param name="peli"></param>
1761    void AsetaFixedSpawnitInfiniteen(Infinite peli)
1762    {
1763        peli.VihollistenFixedSpawnit.Add(new Vector(0, -900));
1764        peli.VihollistenFixedSpawnit.Add(new Vector(960, -270));
1765        peli.VihollistenFixedSpawnit.Add(new Vector(-960, -270));
1766        peli.VihollistenFixedSpawnit.Add(new Vector(0, 1640));
1767        peli.VihollistenFixedSpawnit.Add(new Vector(1300, 920));
1768        peli.VihollistenFixedSpawnit.Add(new Vector(-1300, 920));
1769    }
1770
1771    #endregion
1772
1773    #region pelaaja
1774
1775    /// <summary>
1776    /// Luodaan uusi pelaaja.
1777    /// </summary>
1778    /// <param name="paikka">Paikka, johon pelaaja luodaan ja johon se respawnaa.</param>
1779    /// <param name="leveys">Pelaajan leveys.</param>
1780    /// <param name="korkeus">Pelaajan korkeus.</param>
1781    /// <param name="numero">Pelaajan numero.</param>
1782    /// <param name="kuva">Pelaajan kuva.</param>
1783    /// <param name="kamanVari">Pelaajaan viittaavien objektien väri.</param>
1784    /// <param name="kaytetaankoLaseria">Onko pelaajalla lasertähtäin vai tavallinen piste.</param>
1785    /// <param name="hudinPaikka">Pelaajan HUD:in paikka.</param>
1786    /// <returns>Pelaaja.</returns>
1787    public Pelaaja LuoPelaaja(Vector paikka, double leveys, double korkeus, int numero, Image kuva, Color kamanVari, bool kaytetaankoLaseria, Vector hudinPaikka, bool kaytetaankoTaskulamppua)
1788    {
1789        Pelaaja pelaaja = new Pelaaja(leveys, korkeus, kaytetaankoLaseria, kaytetaankoTaskulamppua); // true: käytetäänkö taskulamppua
1790        pelaaja.CanRotate = false;
1791        pelaaja.Tag = "pelaaja";
1792        pelaaja.LisaaAse(Aseet.LuoPistooli());
1793        pelaaja.LisaaAse(Aseet.LuoNyrkki());
1794        pelaaja.Position = paikka;
1795        pelaaja.SpawnausPaikat.Add(paikka);
1796        pelaaja.Numero = numero;
1797        pelaaja.Image = kuva;
1798        pelaaja.LinearDamping = 0.80;
1799        pelaaja.objektienVari = kamanVari;
1800        pelaaja.elamaPalkki.BarColor = pelaaja.objektienVari;
1801        pelaaja.tahtain = LuoTähtäin(pelaaja.objektienVari);
1802        pelaaja.ValittuAseNaytto = LuoAseNäyttö(hudinPaikka);
1803        pelaaja.ValittuAseNaytto.Text = pelaaja.ValittuAse.AseenNimi;
1804        pelaaja.TappojenMaaraNaytto = LuoTappoNaytto(pelaaja.ValittuAseNaytto.Position);
1805        AddCollisionHandler<Pelaaja, Vihollinen>(pelaaja, delegate(Pelaaja p, Vihollinen v) { Damagea(pelaaja, v.TuhovoimaElaviaKohtaan); });
1806        if (kaytetaankoLaseria)
1807        {
1808            pelaaja.kaytetaankoPalloTahtainta = false;
1809            //pelaaja.tahtain.IsVisible = false;
1810            //AxleJoint aj = new AxleJoint(pelaaja.tahtain, pelaaja);
1811            //aj.Softness = 2;
1812            //Add(aj);
1813        }
1814        return pelaaja;
1815    }
1816
1817    /// <summary>
1818    /// Liikutetaan pelaajaa määrättyyn suuntaan näppäimistöllä.
1819    /// </summary>
1820    /// <param name="pelaaja">Pelaaja, jota liikutetaan.</param>
1821    /// <param name="suunta">Suunta, johon pelaajaa liikutetaan.</param>
1822    void LiikutaPelaajaa(Pelaaja pelaaja, Vector suunta)
1823    {
1824        pelaaja.Move(suunta * pelaaja.Nopeus);
1825    }
1826
1827    /// <summary>
1828    /// Liikutetaan pelaajaa määrättyyn suuntaan Xbox-ohjaimella.
1829    /// </summary>
1830    /// <param name="pelaaja">Pelaaja, jota liikutetaan.</param>
1831    /// <param name="tatinTila">Xbox-ohjaimen analogitatin asento.</param>
1832    void LiikutaPelaajaaPadilla(AnalogState tatinTila, Pelaaja pelaaja)
1833    {
1834        Vector tatinAsento = tatinTila.StateVector;
1835        pelaaja.Move(tatinAsento * pelaaja.Nopeus);
1836        pelaaja.tahtain.Move(tatinAsento * pelaaja.Nopeus);
1837    }
1838
1839    // Tässä kohdassa (LiikutaTahtainta, LiikutaTahtaintaPadilla) ongelmana samat parametrit, mutta eri sisältö.
1840
1841    /// <summary>
1842    /// Liikutetaan pelaajan tähtäintä hiirellä.
1843    /// </summary>
1844    /// <param name="hiirenTila">Ei käytössä, pakollinen parametri.</param>
1845    /// <param name="pelaaja">Pelaaja, jonka tähtäintä liikutetaan.</param>
1846    void LiikutaTahtainta(AnalogState hiirenTila, Pelaaja pelaaja)
1847    {
1848        pelaaja.tahtain.X = Mouse.PositionOnWorld.X;
1849        pelaaja.tahtain.Y = Mouse.PositionOnWorld.Y;
1850    }
1851
1852    /// <summary>
1853    /// Liikutetaan pelaajan tähtäintä Xbox-ohjaimella.
1854    /// </summary>
1855    /// <param name="pelaaja">Pelaaja, jonka tähtäintä liikutetaan.</param>
1856    /// <param name="tatinTila">Xbox-ohjaimen analogitatin asento.</param>
1857    void LiikutaTahtaintaPadilla(AnalogState tatinTila, Pelaaja pelaaja)
1858    {
1859        pelaaja.tahtain.Move(tatinTila.StateVector * 1500);
1860    }
1861
1862    /// <summary>
1863    /// Luodaan uusi tähtäin.
1864    /// </summary>
1865    /// <param name="vari">Tähtäimen väri.</param>
1866    /// <returns>Tähtäin.</returns>
1867    PhysicsObject LuoTähtäin(Color vari)
1868    {
1869        PhysicsObject tähtäin = new PhysicsObject(10.0, 10.0);
1870        tähtäin.Shape = Shape.Circle;
1871        tähtäin.Color = vari;
1872        tähtäin.IgnoresCollisionResponse = true;
1873        tähtäin.IgnoresExplosions = true;
1874        tähtäin.IgnoresPhysicsLogics = true;
1875        tähtäin.LinearDamping = 0.60;
1876        tähtäin.Tag = "tahtain";
1877        Add(tähtäin, 3);
1878        return tähtäin;
1879    }
1880
1881    Label LuoTappoNaytto(Vector ylemmanHudinOsanPaikka)
1882    {
1883        Label tapponaytto = new Label("Tappoja: 0");
1884        tapponaytto.TextColor = Color.White;
1885        tapponaytto.BorderColor = Color.Transparent;
1886        tapponaytto.Position = ylemmanHudinOsanPaikka - new Vector(0.0, 60.0);
1887        Add(tapponaytto);
1888        return tapponaytto;
1889    }
1890
1891    #endregion
1892
1893    #region aseiden toiminnot
1894
1895    /// <summary>
1896    /// Ammutaan pelaajan kulloinkin valittuna olevalla aseella ja
1897    /// luodaan ammukselle törmäyksenkäsittelijät.
1898    /// </summary>
1899    /// <param name="pelaaja">Pelaaja, jonka aseella ammutaan.</param>
1900    /// <param name="overridesIsReady">Annetaan aseen ampua, vaikka se ei oikeasti voisi. Jos true, ääntä ei toisteta.</param>
1901    void Ammu(Pelaaja pelaaja, bool overridesIsReady = false)
1902    {
1903        // pari tarpeellista tarkistusta
1904        if (!pelaaja.IsAddedToGame) return;
1905        if (pelaaja.ValittuAse == null) return;
1906        if (pelaaja.LadataankoAsetta) return;
1907
1908        //pelaaja.ValittuAse.IsReady = true;
1909        PhysicsObject ammus = pelaaja.ValittuAse.Shoot(overridesIsReady);
1910        if (ammus == null) return;
1911
1912        // laitetaan ammus satunnaiseen suuntaan aseen hajoaman mukaan
1913        Vector random = RandomGen.NextVector(pelaaja.ValittuAse.AseenHajoama.X, pelaaja.ValittuAse.AseenHajoama.Y);
1914        if (pelaaja == pelaajat[0])
1915        {
1916            ammusmittariNäyttö.Text = pelaajat[0].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[0].ValittuAse.MaxAmmo.Value.ToString();
1917            if (pelaaja.ValittuAse.OnkoMeleeAse == true) ammusmittariNäyttö.Text = "";
1918            if (pelaaja.ValittuAse.HyokkaysAnimaatio1 != null)
1919            {
1920                pelaajat[0].Animation = pelaaja.ValittuAse.HyokkaysAnimaatio1;
1921                pelaajat[0].Animation.Start(1);
1922            }
1923        }
1924
1925        if (pelaaja == pelaajat[1])
1926        {
1927            ammusmittariNäyttö2.Text = pelaajat[1].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[1].ValittuAse.MaxAmmo.Value.ToString();
1928            if (pelaaja.ValittuAse.OnkoMeleeAse == true) ammusmittariNäyttö2.Text = "";
1929            if (pelaaja.ValittuAse.HyokkaysAnimaatio2 != null)
1930            {
1931                pelaajat[1].Animation = pelaaja.ValittuAse.HyokkaysAnimaatio2;
1932                pelaajat[1].Animation.Start(1);
1933            }
1934        }
1935
1936        ammus.Hit(random);
1937        ammus.CollisionIgnoreGroup = 4;
1938        ammus.Tag = "ammus";
1939        ammus.LinearDamping = 0.99;
1940        ammus.Size = new Vector(pelaaja.ValittuAse.luodinKuva.Width, pelaaja.ValittuAse.luodinKuva.Height);
1941        ammus.Color = Color.White;
1942        ammus.Mass = 0.01;
1943        ammus.CanRotate = false;
1944
1945        // jos on meleease, ei näytetä ammusta
1946        if (pelaaja.ValittuAse.OnkoMeleeAse == true) ammus.IsVisible = false;
1947
1948        // muuten ammutaan hylsy ja laitetaan luodille oikea kuva
1949        else
1950        {
1951            if (pelaaja.ValittuAse.TuleekoHylsya)
1952                Hylsy(pelaaja, pelaaja.ValittuAse.hylsynKuva);
1953            ammus.Image = pelaaja.ValittuAse.luodinKuva;
1954        }
1955
1956        if (pelaaja.ValittuAse.UsesTracers)
1957        {
1958            ammus.IsUpdated = true;
1959            ammus.NeedsUpdateCall = true;
1960            Color c;
1961            if (pelaaja.ValittuAse.OverrideTracerColor != Color.Transparent)
1962                c = pelaaja.ValittuAse.OverrideTracerColor;
1963            else c = pelaaja.objektienVari;
1964            ammus.Updated += delegate(PhysicsObject o) { DrawTracers(o, c, pelaaja.ValittuAse.TracerLength, pelaaja.ValittuAse.TracerBrightness); };
1965        }
1966
1967        if (pelaaja.ValittuAse.IsHoming)
1968        {
1969            ammus.IsUpdated = true;
1970            ammus.NeedsUpdateCall = true;
1971            if (pelaaja == pelaajat[0])
1972                ammus.Updated += delegate(PhysicsObject o) { HakeuduKohteeseen(o, pelaajat[1], 750); };
1973            else
1974                ammus.Updated += delegate(PhysicsObject o) { HakeuduKohteeseen(o, pelaajat[0], 750); };
1975
1976        }
1977
1978        if (pelaaja.ValittuAse.LapaiseekoMateriaaleja)
1979        {
1980            ammus.IgnoresCollisionResponse = true;
1981            ammus.Collided += delegate
1982            {
1983                Timer.SingleShot(pelaaja.ValittuAse.AseenLapaisy, delegate { ammus.IgnoresCollisionResponse = false; });
1984            };
1985        }
1986
1987        AddCollisionHandler<PhysicsObject, Pelaaja>(
1988            ammus, delegate(PhysicsObject a, Pelaaja kohdepelaaja)
1989            {
1990                Damagea(kohdepelaaja, pelaaja.ValittuAse.TuhovoimaElaviaVastaan);
1991                Partikkelit.AddParticleEffect(Partikkelit.VeriPartikkelit, new Vector(a.X, a.Y), 40);
1992                osuma1.Play();
1993                if (ammus != null) ammus.Destroy();
1994            });
1995
1996        AddCollisionHandler<PhysicsObject, Vihollinen>(
1997            ammus, delegate(PhysicsObject a, Vihollinen kohde)
1998            {
1999                Damagea(kohde, pelaaja.ValittuAse.TuhovoimaElaviaVastaan);
2000                Partikkelit.AddParticleEffect(Partikkelit.VeriPartikkelit, new Vector(a.X, a.Y), 40);
2001                osuma1.Play();
2002                if (ammus != null) ammus.Destroy();
2003            });
2004
2005        AddCollisionHandler<PhysicsObject, Tuhoutuva>(
2006            ammus, delegate(PhysicsObject a, Tuhoutuva tuhoutuva)
2007        {
2008            if (tuhoutuva.IsStatic)
2009            {
2010                GameObject luodinJalki = new GameObject(12, 13);
2011                luodinJalki.Image = crack1;
2012                luodinJalki.Position = a.Position;
2013                luodinJalki.Angle = RandomGen.NextAngle();
2014                Add(luodinJalki, 1);
2015                LisaaTehosteObjekti(luodinJalki);
2016                tuhoutuva.Destroyed += delegate
2017                {
2018                    luodinJalki.Destroy();
2019                    tehosteet.Remove(luodinJalki);
2020                };
2021            }
2022
2023            if (pelaaja.ValittuAse.HaviaakoAmmusOsumasta && ammus.IgnoresCollisionResponse == false)
2024            {
2025                a.Destroy();
2026                a.NeedsUpdateCall = false;
2027                switch (RandomGen.NextInt(0, 5))
2028                {
2029                    case 0:
2030                        luotiOsuu.Play();
2031                        break;
2032                    case 1:
2033                        luotiOsuu2.Play();
2034                        break;
2035                    case 2:
2036                        luotiOsuu3.Play();
2037                        break;
2038                    case 3:
2039                        luotiOsuu4.Play();
2040                        break;
2041                    case 4:
2042                        luotiOsuu5.Play();
2043                        break;
2044                }
2045            }
2046            else if (ammus.IgnoresCollisionResponse == true) // ei tuhota
2047            {
2048                switch (RandomGen.NextInt(0, 5))
2049                {
2050                    case 0:
2051                        luotiOsuu.Play();
2052                        break;
2053                    case 1:
2054                        luotiOsuu2.Play();
2055                        break;
2056                    case 2:
2057                        luotiOsuu3.Play();
2058                        break;
2059                    case 3:
2060                        luotiOsuu4.Play();
2061                        break;
2062                    case 4:
2063                        luotiOsuu5.Play();
2064                        break;
2065                }
2066            }
2067            else
2068            {
2069                a.Velocity = new Vector(0.0, 0.0);
2070                a.IgnoresCollisionResponse = true;
2071            }
2072            //tuhoutuva.Kesto.Value -= pelaaja.ValittuAse.TuhovoimaTuhoutuviaVastaan;
2073            Damagea(tuhoutuva, pelaaja.ValittuAse.TuhovoimaTuhoutuviaVastaan);
2074        });
2075
2076        AddCollisionHandler<PhysicsObject, Tuhoutuva>(
2077            ammus, "kivi", delegate(PhysicsObject a, Tuhoutuva kivi)
2078            {
2079                Partikkelit.AddParticleEffect(Partikkelit.KiviPartikkelit, new Vector(a.X, a.Y), 30);
2080                Partikkelit.AddParticleEffect(Partikkelit.KipinaPartikkelit, new Vector(a.X, a.Y), 5);
2081            });
2082
2083        AddCollisionHandler<PhysicsObject, Tuhoutuva>(
2084            ammus, "puu", delegate(PhysicsObject a, Tuhoutuva puu)
2085            {
2086                Partikkelit.AddParticleEffect(Partikkelit.PuuPartikkelit, new Vector(a.X, a.Y), 40);
2087            });
2088        AddCollisionHandler<PhysicsObject, Helikopteri>(
2089            ammus, delegate(PhysicsObject a, Helikopteri kopteri)
2090            {
2091                if (kopteri.OnkoIlmassa) return;
2092
2093                Damagea(kopteri, pelaaja.ValittuAse.TuhovoimaElaviaVastaan);
2094                Partikkelit.AddParticleEffect(Partikkelit.KipinaPartikkelit, new Vector(a.X, a.Y), 40);
2095                a.Destroy();
2096            });
2097
2098        AddCollisionHandler<PhysicsObject, PhysicsObject>(
2099            ammus, "piikkilanka", delegate(PhysicsObject a, PhysicsObject piikkilanka)
2100            {
2101                Partikkelit.AddParticleEffect(Partikkelit.KipinaPartikkelit, new Vector(a.X, a.Y), 40);
2102                //ammus.Destroy();
2103            });
2104        AddCollisionHandler<PhysicsObject, PhysicsObject>(
2105            ammus, delegate(PhysicsObject a, PhysicsObject kohde)
2106            {
2107                if (ammus.IgnoresCollisionResponse == false) a.Destroy();
2108                a.NeedsUpdateCall = false;
2109            });
2110
2111
2112    }
2113
2114    /// <summary>
2115    /// Ammutaan haulikkotyyppisellä aseella.
2116    /// </summary>
2117    /// <param name="pelaaja">Pelaaja, jonka aseella ammutaan.</param>
2118    /// <param name="ammustenMaara">Montako ammusta ammutaan.</param>
2119    void AmmuHaulikolla(Pelaaja pelaaja, int ammustenMaara)
2120    {
2121        if (!pelaaja.ValittuAse.IsReady) return;
2122
2123        pelaaja.ValittuAse.AttackSound.Play();
2124        pelaaja.ValittuAse.Ammo.Value--;
2125        Hylsy(pelaaja, pelaaja.ValittuAse.hylsynKuva);
2126
2127        for (int i = 0; i < ammustenMaara; i++)
2128        {
2129            Ammu(pelaaja, true);
2130        }
2131    }
2132
2133    void MeleeIsku(Pelaaja pelaaja)
2134    {
2135        Ase edellinenAse = pelaaja.ValittuAse;
2136        pelaaja.ValitseAse("nyrkki");
2137        Ammu(pelaaja);
2138        pelaaja.ValitseAse(edellinenAse.Tag.ToString());
2139        PaivitaPelaajanKuvaJaHUD(pelaaja);
2140    }
2141
2142    /// <summary>
2143    /// Ladataan pelaajan kulloinkin valittuna oleva ase.
2144    /// </summary>
2145    /// <param name="pelaaja">Pelaaja, jonka ase ladataan.</param>
2146    void Lataa(Pelaaja pelaaja)
2147    {
2148        // Ammo.Value == valitun aseen senhetkinen lippaassa oleva ammusmäärä
2149        // Ammo.MaxValue == valitun aseen maksimimäärä ammuksia lippaassa
2150        // MaxAmmo.Value == valitun aseen kokonaisammusten maksimimäärä
2151
2152        // jos ammukset täynnä, ei tehdä mitään
2153        if (pelaaja.ValittuAse.Ammo.Value == pelaaja.ValittuAse.Ammo.MaxValue)
2154        {
2155            pelaaja.LadataankoAsetta = false;
2156            return;
2157        }
2158
2159        // montako ammusta on käytetty lippaasta
2160        int lippaastaKaytettyjaAmmuksia = pelaaja.ValittuAse.Ammo.MaxValue - pelaaja.ValittuAse.Ammo.Value;
2161        aseLatausAani.Play();
2162        if (pelaaja.ValittuAse.MaxAmmo.Value >= pelaaja.ValittuAse.Ammo.MaxValue) pelaaja.ValittuAse.Ammo.Value = pelaaja.ValittuAse.Ammo.MaxValue;
2163        else pelaaja.ValittuAse.Ammo.Value = pelaaja.ValittuAse.MaxAmmo.Value;
2164
2165        pelaaja.ValittuAse.MaxAmmo.Value -= lippaastaKaytettyjaAmmuksia;
2166
2167        if (pelaaja == pelaajat[0])
2168        {
2169            ammusmittariNäyttö.Text = pelaajat[0].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[0].ValittuAse.MaxAmmo.Value.ToString();
2170        }
2171        if (pelaaja == pelaajat[1])
2172        {
2173            ammusmittariNäyttö2.Text = pelaajat[1].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[1].ValittuAse.MaxAmmo.Value.ToString();
2174        }
2175        pelaaja.LadataankoAsetta = false;
2176    }
2177
2178    /// <summary>
2179    /// Luo hylsyn pelaajan ampuessa ja lisää sen hylsyt-taulukkoon.
2180    /// </summary>
2181    /// <param name="pelaaja">Pelaaja, jonka aseesta hylsy lentää.</param>
2182    void Hylsy(Pelaaja pelaaja, Image hylsynkuva)
2183    {
2184        PhysicsObject hylsy = new PhysicsObject(2, 5);
2185        hylsy.Image = hylsynkuva;
2186        hylsy.Position = pelaaja.Position + Vector.FromLengthAndAngle(15, pelaaja.Angle + Angle.FromDegrees(-90));
2187        hylsy.LinearDamping = 0.93;
2188        hylsy.Mass = 0.5;
2189        hylsy.Angle = pelaaja.Angle + Angle.FromDegrees(90);
2190        hylsy.AngularVelocity = RandomGen.NextDouble(-20.0, 20.0);
2191        hylsy.AngularDamping = 0.97;
2192        Add(hylsy, -3);
2193
2194        hylsy.MaximumLifetime = TimeSpan.FromSeconds(1.5);
2195        hylsy.Destroying += delegate
2196        {
2197            GameObject fakeHylsy = new GameObject(hylsy.Width, hylsy.Height); // samanlainen GameObject-hylsy samaan paikkaan lagin vähentämiseksi
2198            fakeHylsy.Image = hylsynkuva;
2199            fakeHylsy.Position = hylsy.Position;
2200            fakeHylsy.Angle = hylsy.Angle;
2201            Add(fakeHylsy, -1);
2202            LisaaTehosteObjekti(fakeHylsy);
2203        };
2204
2205        hylsy.Hit(Vector.FromLengthAndAngle(RandomGen.NextInt(150, 300), pelaaja.Angle + Angle.FromDegrees(RandomGen.NextDouble(-95, -85))));
2206        AddCollisionHandler(hylsy, HylsyOsuu);
2207        Timer.SingleShot(0.5, delegate { hylsynPutoamisAani.Play(0.7, 0.0, 0.0); });
2208    }
2209
2210    /// <summary>
2211    /// CollisionHandleri hylsylle. Soitetaan kilahdusääni, jos hylsy osuu seinään.
2212    /// </summary>
2213    /// <param name="hylsy">Hylsy.</param>
2214    /// <param name="kohde">Kohde, johon hylsy osuu.</param>
2215    void HylsyOsuu(PhysicsObject hylsy, PhysicsObject kohde)
2216    {
2217        if (kohde is Tuhoutuva)
2218            hylsynPutoamisAani.Play(0.7, 0.0, 0.0);
2219    }
2220
2221    /// <summary>
2222    /// Heitetään kranaatti, jos pelaaja on lisätty ruudulle ja pelaajalla on kranaatteja jäljellä.
2223    /// </summary>
2224    /// <param name="pelaaja">Pelaaja, joka heittää kranaatin.</param>
2225    void HeitaKranaatti(Pelaaja pelaaja)
2226    {
2227        if (!pelaaja.IsAddedToGame || pelaaja.KranaattienMaara <= 0) return;
2228        const double KRANAATIN_NOPEUS = 25000;
2229        Grenade kranaatti = new Grenade(3.0, TimeSpan.FromSeconds(1.5));
2230        kranaatti.LinearDamping = 0.95;
2231        kranaatti.AngularVelocity = RandomGen.NextDouble(-5.0, 5.0);
2232        kranaatti.AngularDamping = 0.97;
2233        kranaatti.Image = kranaatinKuva;
2234        kranaatti.Explosion.Image = null;
2235        kranaatti.Explosion.ShockwaveColor = Color.Black;
2236        kranaatti.Explosion.IsShockwaveVisible = false;
2237        kranaatti.Explosion.Sound = Aseet.singonAani;
2238        kranaatti.Explosion.Speed = 2000;
2239        kranaatti.Explosion.MaxRadius = 500;
2240        kranaatti.Explosion.ShockwaveReachesObject += delegate(IPhysicsObject kohde, Vector shokki) { RajahdysOsuu(kohde, shokki, kranaatti.Position, Aseet.KRANAATIN_MAKSIMI_DAMAGE); };
2241        kranaatti.Destroying += delegate
2242        {
2243            Partikkelit.AddExplosionEffect(kranaatti.Position, 800);
2244            valo.Position = kranaatti.Position;
2245            valo.Intensity = 2.0;
2246            valo.Distance = 100;
2247            Timer.SingleShot(0.2, delegate { valo.Intensity = 1.5; });
2248            Timer.SingleShot(0.3, delegate { valo.Intensity = 1.0; });
2249            Timer.SingleShot(0.4, delegate { valo.Intensity = 0.5; });
2250            Timer.SingleShot(0.5, delegate { valo.Intensity = 0.0; });
2251        };
2252        kranaatti.IsUpdated = true;
2253        kranaatti.NeedsUpdateCall = true;
2254        kranaatti.Updated += delegate(PhysicsObject p) { DrawTracers(kranaatti.Position, Color.Orange, 0.30, 6); }; // brightness 3
2255        pelaaja.Throw(kranaatti, Angle.FromDegrees(0), KRANAATIN_NOPEUS, 0, 0);
2256        pelaaja.KranaattienMaara--;
2257    }
2258
2259    /// <summary>
2260    /// Annetaan pelaajalle kamaa pelaajan törmätessä laatikkoon.
2261    /// </summary>
2262    /// <param name="laatikko">Laatikko, johon törmätään.</param>
2263    /// <param name="kohde">Pelaaja, joka törmää.</param>
2264    void AnnaKamaa(PhysicsObject laatikko, PhysicsObject kohde)
2265    {
2266        if (kohde.Tag.ToString() == "pelaaja")
2267        {
2268            Pelaaja pelaaja = (kohde as Pelaaja);
2269            Laatikko laat = (laatikko as Laatikko);
2270            Func<Ase>[] aseidenLuontimetodit = { Aseet.LuoRynkky, Aseet.LuoHaulikko, Aseet.LuoMinigun, Aseet.LuoSnipa, Aseet.LuoSinko, /*Aseet.LuoVarsijousi,*/ Aseet.LuoMagnum, Aseet.LuoVintorez };
2271
2272            if (laat.OnkoKäytössä == false)
2273            {
2274                //Ei voi ottaa kamaa käytetystä laatikosta
2275                return;
2276            }
2277            for (int i = 0; i < aseidenLuontimetodit.Length; i++)
2278            {
2279                Ase ase = aseidenLuontimetodit[i]();
2280                if (!pelaaja.OnkoPelaajallaAse(ase.Tag.ToString()))
2281                {
2282                    if (AikaKentanAlusta.SecondCounter.Value > ase.aikaJolloinVoiLuoda)
2283                    {
2284                        pelaaja.LisaaAse(ase);
2285                        MessageDisplay.Add("Pelaaja " + pelaaja.Numero + " sai aseen: " + ase.AseenNimi);
2286                        return;
2287                    }
2288                }
2289            }
2290            Ase satunnainenPelaajanAse;
2291            do
2292                satunnainenPelaajanAse = RandomGen.SelectOne<Ase>(pelaaja.Aseet);
2293            while (satunnainenPelaajanAse.OnkoMeleeAse);
2294
2295            satunnainenPelaajanAse.MaxAmmo.Value = satunnainenPelaajanAse.MaxAmmo.MaxValue;
2296            MessageDisplay.Add("Pelaaja " + pelaaja.Numero + " sai ammuksia aseeseen: " + satunnainenPelaajanAse.AseenNimi);
2297            pelaaja.KranaattienMaara++;
2298            MessageDisplay.Add("Pelaaja " + pelaaja.Numero + " sai kranaatin.");
2299
2300            laatikko.Image = kamaaNäkymätön;
2301            laatikko.IgnoresCollisionResponse = true;
2302            laat.OnkoKäytössä = false;
2303            laat.LaatikonAika.Start();
2304        }
2305    }
2306
2307    /// <summary>
2308    /// Luodaan näyttö, joka näyttää valitun aseen nimen.
2309    /// </summary>
2310    /// <param name="paikka">Näytön paikka.</param>
2311    /// <returns>Näyttö.</returns>
2312    Label LuoAseNäyttö(Vector paikka)
2313    {
2314        Label asenäyttö = new Label();
2315        Add(asenäyttö);
2316        asenäyttö.Position = paikka;
2317        asenäyttö.TextColor = Color.White;
2318        asenäyttö.BorderColor = Color.Transparent;
2319        asenäyttö.Tag = "HUD";
2320        return asenäyttö;
2321    }
2322
2323    /// <summary>
2324    /// Luodaan pelaajan 1 ammusmittari.
2325    /// </summary>
2326    void AmmusMittari()
2327    {
2328        IntMeter ammusmittari = new IntMeter(0);
2329        ammusmittariNäyttö = new Label(
2330        pelaajat[0].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[0].ValittuAse.MaxAmmo.Value.ToString());
2331        ammusmittariNäyttö.X = Screen.Left + 125;
2332        ammusmittariNäyttö.Y = Screen.Top - 100;
2333        ammusmittariNäyttö.TextColor = Jypeli.Color.White;
2334        ammusmittariNäyttö.BorderColor = Jypeli.Color.Transparent;
2335        Add(ammusmittariNäyttö);
2336    }
2337
2338    /// <summary>
2339    /// Luodaan pelaajan 2 ammusmittari.
2340    /// </summary>
2341    void AmmusMittari2()
2342    {
2343        IntMeter ammusmittari2 = new IntMeter(0);
2344        ammusmittariNäyttö2 = new Label(pelaajat[1].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[1].ValittuAse.MaxAmmo.Value.ToString());
2345        ammusmittariNäyttö2.X = Screen.Right - 125;
2346        ammusmittariNäyttö2.Y = Screen.Top - 100;
2347        ammusmittariNäyttö2.TextColor = Jypeli.Color.White;
2348        ammusmittariNäyttö2.BorderColor = Jypeli.Color.Transparent;
2349        Add(ammusmittariNäyttö2);
2350    }
2351
2352    /// <summary>
2353    /// Vaihdetaan asetta ja pelaajan kuvaa.
2354    /// </summary>
2355    /// <param name="pelaaja">Pelaaja, jonka asetta vaihdetaan.</param>
2356    /// <param name="vaihtosuunta">Suunta, johon aselistaa pyöritetään.</param>
2357    void VaihdaAsetta(Pelaaja pelaaja, int vaihtosuunta = 0)
2358    {
2359        if (pelaaja.AseidenMaara < 1) return;
2360        pelaaja.VaihdaAse(Mouse.WheelChange);
2361        pelaaja.VaihdaAse(vaihtosuunta);
2362
2363        PaivitaPelaajanKuvaJaHUD(pelaaja);
2364    }
2365
2366    void PaivitaPelaajanKuvaJaHUD(Pelaaja pelaaja)
2367    {
2368        if (pelaaja == pelaajat[0])
2369        {
2370            pelaaja.Image = pelaaja.ValittuAse.Pelaajan1AseKuva;
2371            ammusmittariNäyttö.Text = pelaajat[0].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[0].ValittuAse.MaxAmmo.Value.ToString();
2372            if (pelaaja.ValittuAse.OnkoMeleeAse == true) ammusmittariNäyttö.Text = "";
2373            pelaaja.ValittuAseNaytto.Text = pelaaja.ValittuAse.AseenNimi;
2374        }
2375
2376        if (pelaaja == pelaajat[1])
2377        {
2378            pelaaja.Image = pelaaja.ValittuAse.Pelaajan2AseKuva;
2379            ammusmittariNäyttö2.Text = pelaajat[1].ValittuAse.Ammo.Value.ToString() + " / " + pelaajat[1].ValittuAse.MaxAmmo.Value.ToString();
2380            if (pelaaja.ValittuAse.OnkoMeleeAse == true) ammusmittariNäyttö2.Text = "";
2381            pelaaja.ValittuAseNaytto.Text = pelaaja.ValittuAse.AseenNimi;
2382        }
2383        pelaaja.ValittuAse.IsVisible = false;
2384    }
2385
2386    /// <summary>
2387    /// Ohjataan hakeutuvaa esinettä kohteeseen.
2388    /// </summary>
2389    /// <param name="hakeutuva">Hakeutuva esine.</param>
2390    /// <param name="kohde">Kohde, jota kohti hakeudutaan.</param>
2391    void HakeuduKohteeseen(PhysicsObject hakeutuva, PhysicsObject kohde, double nopeus)
2392    {
2393        if (hakeutuva.Brain.Owner != null) return;
2394
2395        FollowerBrain fb = new FollowerBrain(kohde);
2396        fb.Speed = nopeus;
2397        fb.TurnWhileMoving = true;
2398        hakeutuva.Brain = fb;
2399    }
2400
2401    #endregion
2402
2403    #region ohjaimet
2404
2405    /// <summary>
2406    /// Asetetaan ohjaimet.
2407    /// </summary>
2408    void AsetaOhjaimet()
2409    {
2410        // Pelaajan 1 ohjaimet
2411        Keyboard.Listen(Key.Escape, Jypeli.ButtonState.Pressed, LuoPauseValikko, "Lopeta peli");
2412        Keyboard.Listen(Key.W, Jypeli.ButtonState.Down, LiikutaPelaajaa, "", pelaajat[0], new Vector(0.0, 1.0));
2413        Keyboard.Listen(Key.S, Jypeli.ButtonState.Down, LiikutaPelaajaa, "", pelaajat[0], new Vector(0.0, -1.0));
2414        Keyboard.Listen(Key.A, Jypeli.ButtonState.Down, LiikutaPelaajaa, "", pelaajat[0], new Vector(-1.0, 0.0));
2415        Keyboard.Listen(Key.D, Jypeli.ButtonState.Down, LiikutaPelaajaa, "", pelaajat[0], new Vector(1.0, 0.0));
2416        Keyboard.Listen(Key.R, Jypeli.ButtonState.Pressed, delegate
2417        {
2418            lippaanPoistoAani.Play();
2419            pelaajat[0].LadataankoAsetta = true;
2420            if (pelaajat[0].ValittuAse.LatausAnimaatio1 != null)
2421            {
2422                pelaajat[0].Animation = new Animation(pelaajat[0].ValittuAse.LatausAnimaatio1);
2423                pelaajat[0].Animation.Start(1);
2424                pelaajat[0].Animation.FPS = pelaajat[0].Animation.FrameCount / pelaajat[0].ValittuAse.LataukseenKuluvaAika;
2425            }
2426            Timer.SingleShot(pelaajat[0].ValittuAse.LataukseenKuluvaAika, delegate { Lataa(pelaajat[0]); });
2427        }, null);
2428        Keyboard.Listen(Key.LeftShift, Jypeli.ButtonState.Pressed, delegate { pelaajat[0].Nopeus = 450.0; ;}, null);
2429        Keyboard.Listen(Key.LeftShift, Jypeli.ButtonState.Released, delegate { pelaajat[0].Nopeus = 300.0; ;}, null);
2430        Keyboard.Listen(Key.E, ButtonState.Pressed, MeleeIsku, null, pelaajat[0]);
2431        Mouse.ListenWheel(delegate { VaihdaAsetta(pelaajat[0]); }, null);
2432        Mouse.Listen(MouseButton.Left, Jypeli.ButtonState.Down, delegate
2433        {
2434            if (pelaajat[0].ValittuAse.BulletsPerShot != 1) AmmuHaulikolla(pelaajat[0], pelaajat[0].ValittuAse.BulletsPerShot);
2435            else Ammu(pelaajat[0]);
2436        }, null);
2437        Mouse.Listen(MouseButton.Right, Jypeli.ButtonState.Pressed, HeitaKranaatti, null, pelaajat[0]);
2438        Mouse.ListenMovement(0.1, LiikutaTahtainta, null, pelaajat[0]);
2439#if DEBUG
2440        Keyboard.Listen(Key.RightControl, ButtonState.Pressed, delegate { MessageDisplay.Add(pelaajat[0].Position.ToString()); }, null);
2441        Keyboard.Listen(Key.P, ButtonState.Pressed, delegate { MessageDisplay.Add(OnkoNaytonAlueella(new Vector(0.0, 0.0)).ToString()); }, null);
2442        Keyboard.Listen(Key.NumPad9, ButtonState.Pressed, delegate { Add(fysLaskuri); }, null);
2443        Keyboard.Listen(Key.C, ButtonState.Down, delegate
2444        {
2445            Vihollinen zombi = new Vihollinen(normaaliZombiKuva.Width / 1.2, normaaliZombiKuva.Height / 1.2, normaaliZombiKuva, 20, 4, 100, pelaajat, false, false, this, null);
2446            Add(zombi);
2447            zombi.Position = pelaajat[0].tahtain.Position;
2448
2449        }, null);
2450        Keyboard.Listen(Key.O, ButtonState.Pressed, LuoHelikopteri, null, pelaajat[0].tahtain.Position);
2451#endif
2452
2453        // Pelaajan 2 ohjaimet
2454        ControllerOne.ListenAnalog(AnalogControl.LeftStick, 0.1, LiikutaPelaajaaPadilla, null, pelaajat[1]);
2455        ControllerOne.Listen(Button.LeftStick, Jypeli.ButtonState.Pressed, delegate { pelaajat[1].Nopeus = 450.0; }, null);
2456        ControllerOne.Listen(Button.LeftStick, Jypeli.ButtonState.Released, delegate { pelaajat[1].Nopeus = 300.0; }, null);
2457        ControllerOne.ListenAnalog(AnalogControl.RightStick, 0.1, LiikutaTahtaintaPadilla, null, pelaajat[1]);
2458        ControllerOne.Listen(Button.RightTrigger, Jypeli.ButtonState.Down, delegate
2459        {
2460            if (pelaajat[1].ValittuAse.BulletsPerShot != 1) AmmuHaulikolla(pelaajat[1], pelaajat[1].ValittuAse.BulletsPerShot);
2461            else Ammu(pelaajat[1]);
2462        }, null);
2463        ControllerOne.Listen(Button.LeftTrigger, Jypeli.ButtonState.Pressed, HeitaKranaatti, null, pelaajat[1]);
2464        ControllerOne.Listen(Button.LeftShoulder, Jypeli.ButtonState.Pressed, delegate { VaihdaAsetta(pelaajat[1], -1); }, null);
2465        ControllerOne.Listen(Button.RightShoulder, Jypeli.ButtonState.Pressed, delegate { VaihdaAsetta(pelaajat[1], 1); }, null);
2466        ControllerOne.Listen(Button.X, Jypeli.ButtonState.Pressed, delegate
2467        {
2468            lippaanPoistoAani.Play(); pelaajat[1].LadataankoAsetta = true;
2469            if (pelaajat[1].ValittuAse.LatausAnimaatio1 != null)
2470            {
2471                pelaajat[1].Animation = new Animation(pelaajat[1].ValittuAse.LatausAnimaatio2);
2472                pelaajat[1].Animation.Start(1);
2473                pelaajat[1].Animation.FPS = pelaajat[1].Animation.FrameCount / pelaajat[1].ValittuAse.LataukseenKuluvaAika;
2474            }
2475            Timer.SingleShot(pelaajat[1].ValittuAse.LataukseenKuluvaAika, delegate { Lataa(pelaajat[1]); });
2476        }, null);
2477        ControllerOne.Listen(Button.A, Jypeli.ButtonState.Pressed, delegate { pelaajat[1].tahtain.Position = pelaajat[1].Position; }, null);
2478        ControllerOne.Listen(Button.RightStick, ButtonState.Pressed, MeleeIsku, null, pelaajat[1]);
2479    }
2480
2481    /// <summary>
2482    /// Otetaan käyttöön sandbox-lisäohjaimet.
2483    /// </summary>
2484    void AsetaSandboxOhjaimet()
2485    {
2486        Keyboard.Listen(Key.Space, ButtonState.Pressed, delegate { SijoitaKentanosaRuudukkoon(pelaajat[0].tahtain.Position); }, null);
2487        Keyboard.Listen(Key.K, ButtonState.Pressed, delegate { LuoKillBall(pelaajat[0].tahtain.Position); }, null);
2488        Keyboard.Listen(Key.T, ButtonState.Pressed, delegate { LuoTynnyri(pelaajat[0].tahtain.Position, 50.0, 50.0, null); }, null);
2489        Keyboard.Listen(Key.Delete, ButtonState.Pressed, RemoveAllEntities, null);
2490        ControllerOne.Listen(Button.B, ButtonState.Pressed, delegate { SijoitaKentanosaRuudukkoon(pelaajat[1].tahtain.Position); }, null);
2491    }
2492
2493    #endregion
2494
2495    #region aseiden osumat
2496
2497    /// <summary>
2498    /// Kutsutaan, kun singon raketti osuu johonkin.
2499    /// </summary>
2500    /// <param name="ammus">Ammus, joka osuu.</param>
2501    /// <param name="kohde">Kohde, johon osutaan.</param>
2502    public void SingonAmmusRajahtaa(PhysicsObject ammus, PhysicsObject kohde)
2503    {
2504        Explosion sinkopaineaalto = new Explosion(200);
2505        sinkopaineaalto.Position = ammus.Position;
2506        sinkopaineaalto.Image = tyhjä;
2507        sinkopaineaalto.Sound = null;
2508        sinkopaineaalto.Force = 400;
2509        sinkopaineaalto.Speed = 1000;
2510        sinkopaineaalto.ShockwaveColor = Color.Black;
2511        sinkopaineaalto.ShockwaveReachesObject += delegate(IPhysicsObject paineaallonKohde, Vector shokki) { RajahdysOsuu(paineaallonKohde, shokki, ammus.Position, Aseet.SINGON_MAKSIMI_DAMAGE); };
2512
2513        Add(sinkopaineaalto);
2514        Aseet.singonAani.Play();
2515
2516        Partikkelit.AddParticleEffect(Partikkelit.RajahdysPartikkelit1, new Vector(kohde.X, kohde.Y), 500);
2517        Partikkelit.AddParticleEffect(Partikkelit.RajahdysPartikkelit2, new Vector(kohde.X, kohde.Y), 300);
2518        ammus.Destroy();
2519
2520        valo.Position = ammus.Position;
2521        valo.Intensity = 2.0;
2522        valo.Distance = 100;
2523        Timer.SingleShot(0.2, delegate { valo.Intensity = 1.5; });
2524        Timer.SingleShot(0.3, delegate { valo.Intensity = 1.0; });
2525        Timer.SingleShot(0.4, delegate { valo.Intensity = 0.5; });
2526        Timer.SingleShot(0.5, delegate { valo.Intensity = 0.0; });
2527    }
2528
2529    /// <summary>
2530    /// Lasketaan räjähdyksen aiheuttama vahinko etäisyyden mukaan.
2531    /// </summary>
2532    /// <param name="rajahdyksenKeskiPiste">Räjähdyksen keskipiste.</param>
2533    /// <param name="kohde">Kohde, johon räjähdys osuu.</param>
2534    /// <param name="maksimivahinko">Vahinko, jonka räjähdys tekee nollapisteessä.</param>
2535    /// <param name="nopeusJollaVahinkoVahenee">Nopeus, jolla räjähdyksen vahinko vähenee etäisyyden kasvaessa. Suurempi luku hidastaa, pienempi nopeuttaa.</param>
2536    /// <returns>Vahinko.</returns>
2537    double LaskeRajahdyksenDamage(Vector rajahdyksenKeskiPiste, Vector kohde, double maksimivahinko, double nopeusJollaVahinkoVahenee)
2538    {
2539        double pisteidenEtaisyys = Vector.Distance(rajahdyksenKeskiPiste, kohde) / nopeusJollaVahinkoVahenee;
2540        double damage = maksimivahinko - pisteidenEtaisyys;
2541        if (damage < 0) return 0;
2542        return damage;
2543    }
2544
2545    /// <summary>
2546    /// Törmäyksenkuuntelija räjähdyksille.
2547    /// </summary>
2548    /// <param name="kohde">Kohde, johon räjähdys osuu.</param>
2549    /// <param name="shokki">Pakollinen parametri.</param>
2550    void RajahdysOsuu(IPhysicsObject kohde, Vector shokki, Vector rajahdyksenAlkamisPiste, double maksimivahinko)
2551    {
2552        double todellinenVahinko = LaskeRajahdyksenDamage(rajahdyksenAlkamisPiste, kohde.Position, maksimivahinko, 8);
2553        if (todellinenVahinko == 0) return;
2554
2555        if (kohde is Tuhoutuva)
2556        {
2557            //Partikkelit.AddParticleEffect(Partikkelit.KiviHajoaa, new Vector(kohde.X, kohde.Y), 50);
2558            //Partikkelit.AddParticleEffect(Partikkelit.PuuHajoaa, new Vector(kohde.X, kohde.Y), 50);
2559            if (kohde != null) Damagea(kohde as Tuhoutuva, todellinenVahinko);
2560        }
2561
2562        if (kohde is Elava)
2563        {
2564            Elava kohdePelaaja = kohde as Elava;
2565            Partikkelit.AddParticleEffect(Partikkelit.VeriPartikkelit, new Vector(kohde.X, kohde.Y), 40);
2566            GameObject[] effects = Blood.AddNormalBlood(kohde.Position, 3, 0.3);
2567            foreach (GameObject blood in effects)
2568            {
2569                LisaaTehosteObjekti(blood);
2570            }
2571            Damagea(kohdePelaaja, todellinenVahinko);
2572        }
2573    }
2574    #endregion
2575}
Note: See TracBrowser for help on using the repository browser.