source: 2015/24/ohjaajat/Dungeon/Dungeon/Dungeon/Dungeon.cs @ 6092

Revision 6092, 29.9 KB checked in by empaheik, 4 years ago (diff)

Taustamusiikki, maksullinen kaivaminen ja mainmenun otsikon säätö.

Line 
1using System;
2using System.Linq;
3using System.Collections.Generic;
4using Jypeli;
5using Jypeli.Assets;
6using Jypeli.Controls;
7using Jypeli.Effects;
8using Jypeli.Widgets;
9using Point = Microsoft.Xna.Framework.Point;
10
11/* Tässä on jotain dokumentaation tapaista:
12 *
13 * Layerit
14 *   3 - Kaivuunuoli ja partikkeliefektit
15 *   2 - Partikkelien varjot
16 *   1 - Huoneiden katto
17 *   0 - Huoneiden seinät ja barbaarit
18 *  -1 - Päivitykset
19 *  -2 - Huone (eli lattiat siis)
20 * 
21 * Ideoita:
22 *  - Pahempia vihollisia, joihin ei tehoa piikkiansat
23 *    vaan pitää ostaa kalliimpia ansoja niitä varten.
24*/
25
26/// <summary>
27/// Päivitys joka voi olla huoneessa.
28/// </summary>
29public abstract class Upgrade : GameObject
30{
31    public int Price { get; set; }
32
33    protected Upgrade()
34        : base(Dungeon.RUUDUN_KOKO, Dungeon.RUUDUN_KOKO)
35    {
36    }
37
38    /// <summary>
39    /// Tätä kutsutaan kun päivitys on rakennettu huoneeseen.
40    /// </summary>
41    public virtual void Built(Dungeon peli) { }
42
43    /// <summary>
44    /// Tätä kutsutaan kun barbaari tulee kylään.
45    /// </summary>
46    public virtual void Invasion(Dungeon peli, Barbaari barbaari, Room huone) { }
47
48    /// <summary>
49    /// Kutsutaan joka syklin alussa.
50    /// </summary>
51    public virtual void SykliPaivitys() { }
52}
53
54class TrapUpgrade : Upgrade
55{
56    public int Damage { get; set; }
57
58    public bool Active
59    {
60        get { return LatausMittari.Value == LatausMittari.MaxValue; }
61    }
62
63    // Jos täynnä, niin ansa on aktiivinen.
64    public IntMeter LatausMittari { get; set; }
65
66    public TrapUpgrade()
67    {
68        LatausMittari = new IntMeter(4, 0, 4);
69        LatausMittari.UpperLimit += delegate
70        {
71            // Askelletaan vikasta framesta ekaan.
72            Animation.Step();
73        };
74    }
75
76    public override void Invasion(Dungeon peli, Barbaari barbaari, Room huone)
77    {
78        if (!Active) return;
79
80        peli.barbaarit.Remove(barbaari);
81        barbaari.Destroy();
82        peli.Splatter(huone.Position);
83
84        // Barbaarin tappo pudottaa latausmittarin nollaan.
85        LatausMittari.Value = LatausMittari.MinValue;
86
87        Animation.StopOnLastFrame = true;
88        Animation.Start(1);
89    }
90
91    public override void SykliPaivitys()
92    {
93        base.SykliPaivitys();
94        if (LatausMittari.Value < LatausMittari.MaxValue)
95        {
96            LatausMittari.Value++;
97        }
98    }
99}
100
101class CultureUpgrade : Upgrade
102{
103    // Tämän päivityksen antama kultuurin määrä.
104    public IntMeter Culture { get; set; }
105
106    // Label joka näyttää päivityksen antaman kultuurin määrän.
107    public Label KultuuriNaytto { get; set; }
108
109    public override void Built(Dungeon peli)
110    {
111        base.Built(peli);
112
113        Culture = new IntMeter(0, 0, 1000);
114
115        // Luodaan kultuurin ilmaisin.
116        KultuuriNaytto = new Label("asd");
117        KultuuriNaytto.TextColor = Color.HotPink;
118        KultuuriNaytto.Color = Color.Black;
119        KultuuriNaytto.Position = peli.Camera.WorldToScreen(this.Position + new Vector(0, Dungeon.RUUDUN_KOKO * 0.5));
120        KultuuriNaytto.BindTo(Culture);
121        peli.Add(KultuuriNaytto);
122
123        // Näytetään kultuurin määrä kun hiiri on päivityksen päällä.
124        var kuuntelija = peli.Mouse.ListenMovement(0.1, _ => KultuuriNaytto.IsVisible = peli.Mouse.IsCursorOn(this), null);
125
126        this.Destroyed += delegate
127        {
128            KultuuriNaytto.Destroy();
129            kuuntelija.Destroy();
130        };
131    }
132
133    public override void Invasion(Dungeon peli, Barbaari barbaari, Room huone)
134    {
135        this.Destroy();
136        huone.Upgrade = null;
137        if (peli.KultuuriHuoneidenPaikat().Count < 1)
138        {
139            peli.LopetaPeli();
140        }
141    }
142}
143
144public class Room : GameObject
145{
146    // Sijainti pelin ruudukossa.
147    public Point Location { get; set; }
148
149    // Päällä näkyvä "katto" kun huone ei ole vielä kaivettu.
150    public GameObject Roof { get; set; }
151
152    // Neljä seinää, jotka on GameObjekteja.
153    public Dictionary<Direction, GameObject> Walls { get; set; }
154
155    // Huoneen sisältämä päivitys.
156    public Upgrade Upgrade { get; set; }
157
158    private bool dug; // Onko huone kaivettu?
159    public bool Dug
160    {
161        get { return dug; }
162        set
163        {
164            dug = value;
165            Roof.IsVisible = !Dug;
166        }
167    }
168
169    public Room(Point paikka)
170        : base(Dungeon.RUUDUN_KOKO, Dungeon.RUUDUN_KOKO)
171    {
172        Walls = new Dictionary<Direction, GameObject>();
173        Location = paikka;
174    }
175}
176
177public class Barbaari : GameObject
178{
179    public List<Point> Reitti { get; set; }
180
181    public Point Kohde { get; set; }
182
183    public Point Location { get; set; }
184
185    public Barbaari(double width, double height)
186        : base(width, height)
187    {
188        Reitti = new List<Point>();
189    }
190}
191
192public class Dungeon : PhysicsGame
193{
194    public const int RUUDUN_KOKO = 64;
195
196    public static Func<int, int, string, Image[]> LoadImages2 = (a, b, fmt) =>
197        LoadImages((from i in Enumerable.Range(a, b) select string.Format(fmt, i)).ToArray());
198
199    #region Kuvat
200    Image lattiaKuva = LoadImage("floor");
201    Image seinaKuva = LoadImage("wall");
202    Image reikaSeinaKuva = LoadImage("wallhole");
203    Image kiviKuva = LoadImage("rock");
204    Image[] kultuuriKuvat = LoadImages("nyan", "es", "spurdo");
205    private Image[] piikkiAnsaKuvat = LoadImages2(1, 7, "piikit/piikit{0:0000}");
206    private Image[] murskausAnsaKuvat = LoadImages2(1, 9, "smash/smash{0:0000}");
207    public Image[] vihuKuvat = LoadImages2(1, 10, "vihu/v{0:0000}");
208    public Image[] kirvesVihuKuvat = LoadImages2(1, 10, "kirvesvihu/kv{0:0000}");
209    Image[] ansaKuvat;
210    Image partikkeliKuva = LoadImage("partikkeli");
211    Image taideVeri = LoadImage("taideveri");
212    #endregion
213
214    int[] hinnat = { 100, 200, 300, 100 };
215    int[] ansaHinnat = { 400, 800 };
216    private int barbaariMaara = 2;
217
218    private Label kierrosIlmaisin;
219    private bool kierrosKaynnissa;
220    public bool KierrosKaynnissa
221    {
222        get
223        {
224            return kierrosKaynnissa;
225        }
226        set
227        {
228            kierrosKaynnissa = value;
229            kierrosIlmaisin.Text = "Vaihe: " + (kierrosKaynnissa ? "Barbaari-invaasio" : "Rakennusvaihe");
230        }
231    }
232
233    Room[,] huoneet;
234    //public List<Room> kohteet = new List<Room>();
235    public List<Barbaari> barbaarit = new List<Barbaari>();
236    Room spawn;
237    Timer barbaariAjastin = new Timer();
238    Upgrade ostamassa;
239    Point digStart; // Huoneen sijainti, josta kaivuu aloitetaan.
240    bool digging = false;
241
242    GameObject digArrow;
243    GameObject digArrowHead;
244
245    IntMeter kultuuri = new IntMeter(1000, 0, 2000);
246
247    const int VAAKA_HUONEET = 12;
248    const int PYSTY_HUONEET = 8;
249
250    // Paljonko peliruudukko on siirtynyt origosta.
251    Vector huoneSiirtyma = new Vector(-200, 0);
252
253    private MainMenu menu;
254
255    public override void Begin()
256    {
257        SmoothTextures = false;
258        IsMouseVisible = true;
259
260        //SetWindowSize(1024, 768); Riippuu vähän Jypelin versiosta.
261        Window.Width = 1024;
262        Window.Height = 768;
263
264        ansaKuvat = new Image[] {piikkiAnsaKuvat[0], murskausAnsaKuvat[0]};
265        menu = new MainMenu(this, "New game", "Highscores", "Help", "Quit");
266        menu.Painikkeet[0].Clicked += AloitaPeli;
267        menu.Painikkeet[3].Clicked += Exit;
268    }
269
270    void AloitaPeli()
271    {
272        ClearAll();
273        MediaPlayer.Play("In_The_Dark_Flashes");
274        Kontrollit();
275        UlkoAsuRoskaa();
276        Kauppa();
277        Nuoli();
278
279        // Luodaan huoneet ruutuihin.
280        huoneet = new Room[VAAKA_HUONEET, PYSTY_HUONEET];
281        foreach (var paikka in RuutujenPaikat())
282        {
283            var huone = CreateRoom(paikka);
284            Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Pressed, () => RoomPressed(huone), null);
285            Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Released, () => RoomReleased(huone), null);
286            Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Pressed, AsetaPaivitys, "Asetetaan ostettu päivitys paikoilleen", huone);
287            Mouse.Listen(MouseButton.Right, ButtonState.Pressed, delegate { ostamassa = null; }, "Perutaan ostos");
288            Mouse.ListenOn(huone, MouseButton.Right, ButtonState.Pressed, PoistaPaivitys, "Poistetaan asetettu päivitys", huone);
289            huoneet[paikka.X, paikka.Y] = huone;
290        }
291
292        LuoSpawn();
293
294        Timer sykliAjastin = new Timer { Interval = 1.0 };
295        sykliAjastin.Timeout += Sykli;
296        sykliAjastin.Start();
297
298        barbaariAjastin.Timeout += LuoBarbaareja;
299        barbaariAjastin.Interval = 3;
300
301        Level.Width = 1300;
302        Camera.ZoomToLevel();
303    }
304
305    void Nuoli()
306    {
307        digArrow = new GameObject(5, 5);
308        digArrowHead = new GameObject(15, 15);
309        digArrowHead.Shape = Shape.Triangle;
310        digArrowHead.IsVisible = digArrow.IsVisible = false;
311        Add(digArrow, 3);
312        Add(digArrowHead, 3);
313    }
314
315    void UlkoAsuRoskaa()
316    {
317        Level.Background.Color = Color.Black;
318
319        kierrosIlmaisin = new Label("asd");
320        kierrosIlmaisin.TextColor = Color.White;
321        kierrosIlmaisin.Y = Screen.Top - 150;
322        Add(kierrosIlmaisin);
323        KierrosKaynnissa = KierrosKaynnissa; // Aiheuttaa labelin päivittymisen.
324
325        Label rahat = new Label();
326        rahat.BindTo(kultuuri);
327        rahat.Position = new Vector(Screen.Right - 200, Screen.Bottom + 50);
328        //rahat.Position = new Vector(Level.Right + Level.Width * 0.2, Level.Bottom + Level.Height * 0.1);
329        rahat.TextColor = Color.White;
330        rahat.IntFormatString = "Käytettävää kulttuuria: {0:D3}";
331        Add(rahat);
332    }
333
334    public void LopetaPeli()
335    {
336        ClearAll();
337        GameObject spurdo = new GameObject(Screen.Width, Screen.Height);
338        spurdo.Image = kultuuriKuvat[2];
339        Add(spurdo);
340
341        Label havisit = new Label("Hävisit muuten belin");
342        havisit.Color = Color.HotPink;
343        havisit.Size = new Vector(300, 300);
344        havisit.Position = new Vector(Level.Right - havisit.Width * 0.5, Level.Top - havisit.Height * 0.5);
345        Add(havisit);
346    }
347
348    void Kauppa()
349    {
350        for (int i = 0; i < kultuuriKuvat.Length; i++)
351        {
352            PushButton kuva = new PushButton(kultuuriKuvat[i]);
353            kuva.Size = new Vector(1, 1) * RUUDUN_KOKO;
354            kuva.X = Window.ClientBounds.Width / 2 - 200;
355            kuva.Y = Window.ClientBounds.Height / 2 - (100 + RUUDUN_KOKO * i);
356            //kuva.Position = new Vector((Level.Right + Level.Width * 0.05), (Level.Top - Level.Height * 0.25 - (i * RUUDUN_KOKO)));
357            //kuva.Position = new Vector(Window.ClientBounds.Right, 0);
358            Add(kuva);
359
360            int indeksi = i; // Alla oleva delegaatti vaatii uuden indeksi muuttujan toimiakseen.
361            kuva.Clicked += delegate
362            {
363                ostamassa = LuoKultuuriPaivitys(kultuuriKuvat[indeksi], hinnat[indeksi]);
364            };
365             
366            Add(new Label
367            {
368                Position = kuva.Position + new Vector((RUUDUN_KOKO * 1.2), 0),
369                TextColor = Color.White,
370                Text = hinnat[i].ToString()
371            });
372        }
373
374        for (int i = 0; i < ansaKuvat.Length; i++)
375        {
376            PushButton kuva = new PushButton(ansaKuvat[i]);
377            kuva.Size = new Vector(1, 1) * RUUDUN_KOKO;
378            kuva.Color = Color.Gray;
379            kuva.X = Window.ClientBounds.Width / 2 - 200;
380            kuva.Y = Window.ClientBounds.Height / 2 - (100 + RUUDUN_KOKO * (kultuuriKuvat.Count() + i));
381            //kuva.Position = new Vector((Level.Right + Level.Width * 0.05), (Level.Top - Level.Height * 0.25 - ((kultuuriKuvat.Count() + i) * RUUDUN_KOKO)));
382            Add(kuva);
383
384            int indeksi = i;
385            kuva.Clicked += delegate
386            {
387                ostamassa = LuoAnsaPaivitys(ansaKuvat[ansaKuvat.Length - 1], ansaHinnat[indeksi]);
388            };
389
390            Add(new Label
391            {
392                Position = kuva.Position + new Vector((RUUDUN_KOKO * 1.2), 0),
393                TextColor = Color.White,
394                Text = ansaHinnat[i].ToString()
395            });
396        }
397    }
398
399    Upgrade LuoAnsaPaivitys(Image kuva, int hinta)
400    {
401        return new TrapUpgrade
402        {
403            Image = kuva,
404            Size = new Vector(0.5, 0.5) * RUUDUN_KOKO,
405            Price = hinta,
406            Animation = new Animation(piikkiAnsaKuvat)
407        };
408    }
409
410    Upgrade LuoKultuuriPaivitys(Image kuva, int hinta)
411    {
412        return new CultureUpgrade
413        {
414            Image = kuva,
415            Size = new Vector(0.5, 0.5) * RUUDUN_KOKO,
416            Price = hinta
417        };
418    }
419
420    void LuoBarbaareja()
421    {
422        Barbaari barbaari = new Barbaari(RUUDUN_KOKO * 0.4, RUUDUN_KOKO * 0.4);
423        barbaari.Color = Color.Red;
424        barbaari.Position = spawn.Position;
425        barbaari.Animation = new Animation(vihuKuvat) { FPS = 10 };
426        barbaari.Animation.Start();
427        barbaari.Location = spawn.Location;
428        Add(barbaari);
429        barbaarit.Add(barbaari);
430
431        EtsiBarbaarinReitti(barbaari);
432    }
433
434    void EtsiBarbaarinReitti(Barbaari barbaari)
435    {
436        var kohteet = KultuuriHuoneidenPaikat();
437        barbaari.Kohde = kohteet[RandomGen.NextInt(kohteet.Count)];
438        barbaari.Reitti = FindPath(barbaari.Kohde, (barbaari.Location.Equals(spawn.Location)) ? spawn.Location : barbaari.Location);
439    }
440
441    public List<Point> KultuuriHuoneidenPaikat()
442    {
443        return RuutujenPaikat().Select(GetRoom).Where(r => r.Upgrade != null && r.Upgrade is CultureUpgrade).Select(r => r.Location).ToList();
444    }
445
446    void Sykli()
447    {
448        // Päivitetään huoneiden päivityksiä.
449        RuutujenPaikat().Select(GetRoom).Where(r => r.Upgrade != null).ToList().ForEach(r => r.Upgrade.SykliPaivitys());
450
451        // Päivitetään barbaareja.
452        foreach (var barbaari in barbaarit)
453        {
454            if (barbaari.Reitti.Count == 0)
455            {
456                EtsiBarbaarinReitti(barbaari);  //Etsitään uusi reitti poiston sijaan.
457                continue;
458            }
459
460            Point seuraavaPaikka = barbaari.Reitti[0];
461            barbaari.Reitti.RemoveAt(0);
462            Barbaari b = barbaari;
463            barbaari.MoveTo(huoneet[seuraavaPaikka.X, seuraavaPaikka.Y].Position, 100, () => SyklinPaatteeksi(b, seuraavaPaikka));
464        }
465
466        // Tarkistetaan onko barbaariaalto jo ohi.
467        if (KierrosKaynnissa && barbaarit.Count == 0 && barbaariAjastin.Times == barbaariAjastin.Times.MinValue)
468        {
469            KierrosKaynnissa = false;
470
471            // Annetaan pelaajalle kultuuripisteet.
472            foreach (var huone in KultuuriHuoneidenPaikat().Select(GetRoom))
473            {
474                CultureUpgrade upg = huone.Upgrade as CultureUpgrade;
475                if (upg == null)
476                    continue;
477
478                kultuuri.Value += upg.Culture;
479                Label ilmoitus = new Label("+" + upg.Culture);
480                ilmoitus.TextColor = Color.HotPink;
481                ilmoitus.Color = Color.Black;
482                ilmoitus.Position = Camera.WorldToScreen(huone.Position);
483                Add(ilmoitus);
484
485                double kohdeY = ilmoitus.Y + 50;
486                var liikutusAjastin = new Timer();
487                liikutusAjastin.Interval = 0.02;
488                liikutusAjastin.Timeout += delegate
489                {
490                    ilmoitus.Y += (kohdeY - ilmoitus.Y) * 0.05;
491                };
492                liikutusAjastin.Start();
493
494                ilmoitus.LifetimeLeft = TimeSpan.FromSeconds(2.0);
495                ilmoitus.Destroyed += liikutusAjastin.Stop;
496            }
497        }
498    }
499
500    void SyklinPaatteeksi(Barbaari barbaari, Point uusiPaikka)
501    {
502        // Barbaari saapui juuri uusiPaikka kohdassa olevaan huoneeseen.
503        // Tässä pitäisi katsoa mitä huoneessa tapahtuu.
504        barbaari.Location = uusiPaikka;
505
506        Room huone = huoneet[uusiPaikka.X, uusiPaikka.Y];
507
508        if (huone.Upgrade != null)
509        {
510            huone.Upgrade.Invasion(this, barbaari, huone);
511        }
512    }
513
514    void Kontrollit()
515    {
516        IsMouseVisible = true;
517        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, "Näytä valikko");
518        Keyboard.Listen(Key.F1, ButtonState.Pressed, Begin, null);
519
520        Keyboard.Listen(Key.Space, ButtonState.Pressed, SeuraavaAalto, "Anna kivan barbaariaallon tulla");
521    }
522
523    void SeuraavaAalto()       
524    {
525        if (KultuuriHuoneidenPaikat().Count == 0 || KierrosKaynnissa) return;
526
527        barbaariAjastin.Start(barbaariMaara);
528        barbaariMaara += 2;
529        KierrosKaynnissa = true;
530    }
531
532    void LuoSpawn()
533    {
534        spawn = huoneet[(int)(huoneet.GetLength(0) * 0.5), 0];
535        spawn.Dug = true;
536
537        Direction oviSuunta = Direction.Down;
538        spawn.Walls[oviSuunta].Image = reikaSeinaKuva;
539
540        spawn.Upgrade = new TrapUpgrade();      //TODO: Parempi tapa varmistaa, että spawniin ei pysty rakentamaan mitään? Oma upgradetyyppi?
541        TrapUpgrade upg = spawn.Upgrade as TrapUpgrade;
542        upg.LatausMittari = new IntMeter(0, 0, 0);
543
544        Light valo = new Light();
545        valo.Position = spawn.Position;
546        valo.Intensity = 1;
547        valo.Distance = 40;
548        Add(valo);
549    }
550
551    void RoomPressed(Room huone)
552    {
553        digStart = huone.Location;
554        digging = true;
555        digArrowHead.IsVisible = digArrow.IsVisible = true;
556    }
557
558    void RoomReleased(Room kohdeHuone)
559    {
560        digging = false;
561        digArrowHead.IsVisible = digArrow.IsVisible = false;
562        if (!CanDig()) return;
563
564        int dx = kohdeHuone.Location.X - digStart.X;
565        int dy = kohdeHuone.Location.Y - digStart.Y;
566        Point[] kaivettavatPaikat = RuudutSuoralta(digStart, dx, dy).ToArray();
567        for (int i = 0; i < kaivettavatPaikat.Length - 1; i++)
568        {
569            Dig(GetRoom(kaivettavatPaikat[i]), GetRoom(kaivettavatPaikat[i + 1]));
570        }
571
572        // Päivitetään huoneiden kultuuri-infot.
573        PaivitaHuoneidenKultuurit();
574    }
575
576    void Dig(Room alku, Room kohde)
577    {
578        // Hienot partikkeliefektit.
579        if (!alku.Dug)
580            LuoKiviPartikkelit(alku.Position);
581        if (!kohde.Dug)
582            LuoKiviPartikkelit(kohde.Position);
583
584        // Merkataan huoneet kaivetuksi ja maksetaan siitä kivasti.
585        alku.Dug = kohde.Dug = true;
586        kultuuri.Value -= 50;
587
588        // Reiät seinään.
589        Direction oviSuunta = (kohde.Position - alku.Position).Angle.MainDirection;
590        Direction toinenOviSuunta = Direction.Inverse(oviSuunta);
591        alku.Walls[oviSuunta].Image = reikaSeinaKuva;
592        kohde.Walls[toinenOviSuunta].Image = reikaSeinaKuva;
593    }
594
595    Room CreateRoom(Point paikka)
596    {
597        Room huone = new Room(paikka);
598        huone.Image = lattiaKuva;
599        huone.Position = new Vector(paikka.X - huoneet.GetLength(0) / 2, paikka.Y - huoneet.GetLength(1) / 2) * RUUDUN_KOKO;
600        huone.Position += huoneSiirtyma;
601        foreach (var suunta in Suunnat())
602            huone.Walls[suunta] = CreateWall(huone.Position, suunta);
603        Add(huone, -2);
604        huone.Roof = new GameObject(RUUDUN_KOKO, RUUDUN_KOKO);
605        huone.Roof.Image = kiviKuva;
606        huone.Roof.Position = huone.Position;
607        Add(huone.Roof, 1);
608
609        //Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Pressed, AsetaPaivitys, "Asetetaan ostettu päivitys paikoilleen", huone);
610        //Mouse.Listen(MouseButton.Right, ButtonState.Pressed, delegate { ostamassa = null; }, "Perutaan ostos");
611        //Mouse.ListenOn(huone, MouseButton.Right, ButtonState.Pressed, PoistaPaivitys, "Poistetaan asetettu päivitys", huone);
612
613        return huone;
614    }
615
616    private void PoistaPaivitys(Room huone)
617    {
618        if (huone.Upgrade != null)
619        {
620            kultuuri.Value += (int)(huone.Upgrade.Price * 0.5);
621            huone.Upgrade.Destroy();
622            huone.Upgrade = null;
623        }
624    }
625
626    void AsetaPaivitys(Room huone)
627    {
628        if (ostamassa != null && huone.Dug && kultuuri.Value >= ostamassa.Price && huone.Upgrade == null) //Varmistetaan, että kahta päivitystä ei laiteta päällekäin
629        {
630            kultuuri.Value -= ostamassa.Price;
631
632            // Lisätään päivitys huoneeseen.
633            huone.Upgrade = ostamassa;
634            Add(huone.Upgrade, -1);
635            huone.Upgrade.Position = huone.Position;
636            huone.Upgrade.Built(this);
637
638            ostamassa = null;
639            PaivitaHuoneenKultuuri(huone);
640        }
641    }
642
643    void PaivitaHuoneidenKultuurit()
644    {
645        RuutujenPaikat().Select(GetRoom).ToList().ForEach(PaivitaHuoneenKultuuri); // :D ;___;; MIKSI <- koska pystyn
646    }
647
648    void PaivitaHuoneenKultuuri(Room room)
649    {
650        if (room != null && room.Upgrade != null && room.Upgrade is CultureUpgrade)
651        {
652            var upg = room.Upgrade as CultureUpgrade;
653
654            List<Point> polku = FindPath(room.Location, spawn.Location);
655            upg.Culture.Value = Math.Max(0, 150 - 5 * polku.Count);
656        }
657    }
658
659    GameObject CreateWall(Vector paikka, Direction suunta)
660    {
661        GameObject wall = new GameObject(RUUDUN_KOKO + 2, RUUDUN_KOKO + 2);
662        wall.Position = paikka;
663        wall.Image = seinaKuva;
664        wall.Angle = suunta.Angle;
665        Add(wall, 0);
666        return wall;
667    }
668
669    bool CanDig()
670    {
671        Room kohdeHuone = GetRoom(MuunnaJypelista(Mouse.PositionOnWorld));
672        if (kohdeHuone == null || kierrosKaynnissa)
673        {
674            return false;
675        }
676
677        int dx = Math.Abs(kohdeHuone.Location.X - digStart.X);
678        int dy = Math.Abs(kohdeHuone.Location.Y - digStart.Y);
679        return (dx > 0 && dy == 0) || (dy > 0 && dx == 0);
680    }
681
682    #region Reitinlöytö
683
684    List<Point> FindPath(Point alku, Point loppu)
685    {
686        if (GetRoom(alku) == null || GetRoom(loppu) == null)
687            return new List<Point>();
688
689        bool[,] walkable = new bool[huoneet.GetLength(0), huoneet.GetLength(1)];
690        foreach (var paikka in RuutujenPaikat())
691        {
692            walkable[paikka.X, paikka.Y] = huoneet[paikka.X, paikka.Y].Dug;
693        }
694        var finder = new AStar.PathFinder(new AStar.SearchParameters(loppu, alku, walkable), OviTarkistus);
695        return finder.FindPath();
696    }
697
698    bool OviTarkistus(Point a, Point b)
699    {
700        Room ra = GetRoom(a);
701        Room rb = GetRoom(b);
702        Direction suunta = (new Vector(b.X, b.Y) - new Vector(a.X, a.Y)).Angle.MainDirection;
703        if (ra != null && rb != null)
704        {
705            return ra.Walls[suunta].Image == reikaSeinaKuva && rb.Walls[Direction.Inverse(suunta)].Image == reikaSeinaKuva;
706        }
707        return false;
708    }
709
710    #endregion
711
712    #region Extra Juttuja
713
714    IEnumerable<Direction> Suunnat()
715    {
716        yield return Direction.Left;
717        yield return Direction.Right;
718        yield return Direction.Up;
719        yield return Direction.Down;
720    }
721
722    IEnumerable<Point> RuutujenPaikat()
723    {
724        return from y in Enumerable.Range(0, huoneet.GetLength(1))
725               from x in Enumerable.Range(0, huoneet.GetLength(0))
726               select new Point(x, y);
727    }
728
729    /// <summary>
730    /// Palauttaa ruutuja suoralta pätkältä dx ja dy verran alkaen pisteestä "alku".
731    /// dx tai dy pitää olla nolla.
732    /// </summary>
733    IEnumerable<Point> RuudutSuoralta(Point alku, int dx, int dy)
734    {
735        if (dx != 0)
736        {
737            for (int i = 0; i < Math.Abs(dx) + 1; i++)
738            {
739                yield return new Point(alku.X + i * Math.Sign(dx), alku.Y);
740            }
741            yield break;
742        }
743        if (dy != 0)
744        {
745            for (int i = 0; i < Math.Abs(dy) + 1; i++)
746            {
747                yield return new Point(alku.X, alku.Y + i * Math.Sign(dy));
748            }
749        }
750    }
751
752    Room GetRoom(Point paikka)
753    {
754        if (paikka.X >= 0 && paikka.X < huoneet.GetLength(0) && paikka.Y >= 0 && paikka.Y < huoneet.GetLength(1))
755        {
756            return huoneet[paikka.X, paikka.Y];
757        }
758        return null;
759    }
760
761    /// <summary>
762    /// Muuntaa Jypeli-koordinaatin peliruudukon koordinaatiksi.
763    /// </summary>
764    Point MuunnaJypelista(Vector paikka)
765    {
766        Vector siirrettyOrigo = (paikka - huoneSiirtyma) + RUUDUN_KOKO * (0.5 * new Vector(huoneet.GetLength(0), huoneet.GetLength(1)) + new Vector(0.5, 0.5));
767        Vector wtf = new Vector(siirrettyOrigo.X < 0 ? -1 : 0, siirrettyOrigo.Y < 0 ? -1 : 0);
768        Vector valmis = wtf + siirrettyOrigo / RUUDUN_KOKO;
769        return new Point((int)valmis.X, (int)valmis.Y);
770    }
771
772    public void LuoLentavaPartikkeli(Vector alkupaikka, Image kuva, double koko, int maara, bool veri = false)
773    {
774        // Feikki 3D partikkeli juttu.
775        // Heittää ilmaan GameObjekteja joiden alla on varjo.
776
777        // VAROITUS: SISÄLTÄÄ JÄRKYTTÄVÄÄ KOODIA
778
779        for (int i = 0; i < maara; i++)
780        {
781            GameObject partikkeli = new GameObject(koko, koko);
782            partikkeli.Image = kuva;
783            partikkeli.Position = alkupaikka + RandomGen.NextVector(0.0, RUUDUN_KOKO * 0.4);
784            Add(partikkeli, 3);
785
786            GameObject varjo = new GameObject(koko, koko / 2.0);
787            varjo.Position = partikkeli.Position;
788            varjo.Shape = Shape.Circle;
789            varjo.Color = Color.Lerp(Color.Black, Color.Transparent, 0.5);
790            Add(varjo, 2);
791
792            Vector paikka = partikkeli.Position;
793            Vector nopeus = RandomGen.NextVector(0.2, 3.0);
794            nopeus.Y *= 0.3;
795            double g = -0.2; // painovoima
796            double z = 0.0; // sijainti z-akselilla
797            double vz = RandomGen.NextDouble(3.5, 4.5); // nopeus z-akselilla
798            double angularVelocity = RandomGen.NextDouble(-1.0, 1.0) * 8;
799
800            var verenLuontiAjastin = veri ? new Timer() : null;
801
802            var ajastin = new Timer();
803            ajastin.Interval = 0.02;
804            ajastin.Timeout += delegate
805            {
806                vz += g;
807                z += vz;
808                paikka += nopeus;
809                partikkeli.Position = paikka + new Vector(0.0, 1.0) * z;
810                partikkeli.Angle += Angle.FromDegrees(angularVelocity);
811                varjo.Position = paikka;
812
813                if (z < 0.0)
814                {
815                    ajastin.Stop();
816                    partikkeli.Destroy();
817                    varjo.Destroy();
818                    if (verenLuontiAjastin != null)
819                        verenLuontiAjastin.Stop();
820                }
821            };
822            ajastin.Start();
823
824            if (verenLuontiAjastin != null)
825            {
826                verenLuontiAjastin.Interval = 0.1;
827                verenLuontiAjastin.Timeout += delegate
828                {
829                    GameObject veriPartikkeli = new GameObject(3, 3);
830                    veriPartikkeli.Color = Color.DarkRed;
831                    Add(veriPartikkeli, 2);
832
833                    Vector veriPaikka = paikka;
834                    double veriZ = z;
835                    double veriVz = 0.0;
836
837                    var veriPaivitysAjastin = new Timer();
838                    veriPaivitysAjastin.Interval = 0.02;
839                    veriPaivitysAjastin.Timeout += delegate
840                    {
841                        veriVz += g;
842                        veriZ += veriVz;
843                        veriPartikkeli.Position = veriPaikka + new Vector(0.0, 1.0) * veriZ;
844
845                        if (veriZ < 0.0)
846                        {
847                            veriPaivitysAjastin.Stop();
848                            veriPartikkeli.Destroy();
849                        }
850                    };
851                    veriPaivitysAjastin.Start();
852                };
853                verenLuontiAjastin.Start();
854            }
855        }
856    }
857
858    void LuoKiviPartikkelit(Vector alkupaikka)
859    {
860        LuoLentavaPartikkeli(alkupaikka, partikkeliKuva, 25, 6);
861    }
862
863    public void Splatter(Vector alkupaikka)
864    {
865        LuoLentavaPartikkeli(alkupaikka, taideVeri, 8, 10, true);
866    }
867
868    protected override void Update(Time time)
869    {
870        if (digging)
871        {
872            Color vari = CanDig() ? Color.White : Color.Red;
873            Vector alku = huoneet[digStart.X, digStart.Y].Position;
874            Vector loppu = Mouse.PositionOnWorld;
875            Vector suunta = loppu - alku;
876            double pituus = suunta.Magnitude;
877            if (pituus <= 2) pituus = 2;
878
879            digArrow.Color = vari;
880            digArrow.Position = alku + suunta * 0.5;
881            digArrow.Angle = suunta.Angle;
882            digArrow.Width = pituus;
883
884            digArrowHead.Color = vari;
885            digArrowHead.Position = alku + suunta;
886            digArrowHead.Angle = suunta.Angle - Angle.FromDegrees(90);
887        }
888
889        if (menu != null)
890            menu.Update(time);
891        base.Update(time);
892    }
893
894    /*
895    protected override void Paint(Canvas canvas)
896    {
897        canvas.BrushColor = Color.Purple;
898
899        var points = FindPath(new Point(6, 0), MuunnaJypelista(Mouse.PositionOnWorld));
900        for (int i = 0; i < points.Count - 1; i++)
901        {
902            Vector v = huoneSiirtyma + new Vector(points[i].X - huoneet.GetLength(0) / 2, points[i].Y - huoneet.GetLength(1) / 2) * RUUDUN_KOKO;
903            Vector v2 = huoneSiirtyma + new Vector(points[i + 1].X - huoneet.GetLength(0) / 2, points[i + 1].Y - huoneet.GetLength(1) / 2) * RUUDUN_KOKO;
904            canvas.DrawLine(v, v2);
905        }
906
907        base.Paint(canvas);
908    }
909    */
910
911    #endregion
912}
Note: See TracBrowser for help on using the repository browser.