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

Revision 6041, 25.2 KB checked in by sieerinn, 5 years ago (diff)

Kierrokset.

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