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

Revision 6048, 28.9 KB checked in by empaheik, 4 years ago (diff)
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    #region Kuvat
197    Image lattiaKuva = LoadImage("floor");
198    Image seinaKuva = LoadImage("wall");
199    Image reikaSeinaKuva = LoadImage("wallhole");
200    Image kiviKuva = LoadImage("rock");
201    Image[] kultuuriKuvat = LoadImages("nyan", "es", "spurdo");
202    Image[] ansaKuvat = LoadImages((from i in Enumerable.Range(1, 7) select String.Format("piikit{0:0000}", i)).ToArray());
203    Image[] vihuKuvat = LoadImages((from i in Enumerable.Range(1, 10) select String.Format("v{0:0000}", i)).ToArray());
204    Image partikkeliKuva = LoadImage("partikkeli");
205    Image taideVeri = LoadImage("taideveri");
206    #endregion
207
208    int[] hinnat = { 100, 200, 300, 100 };
209    int[] ansaHinnat = { 400 };
210    private int barbaariMaara = 2;
211
212    private Label kierrosIlmaisin;
213    private bool kierrosKaynnissa;
214    public bool KierrosKaynnissa
215    {
216        get
217        {
218            return kierrosKaynnissa;
219        }
220        set
221        {
222            kierrosKaynnissa = value;
223            kierrosIlmaisin.Text = "Vaihe: " + (kierrosKaynnissa ? "Barbaari-invaasio" : "Rakennusvaihe");
224        }
225    }
226
227    Room[,] huoneet;
228    //public List<Room> kohteet = new List<Room>();
229    public List<Barbaari> barbaarit = new List<Barbaari>();
230    Room spawn;
231    Timer barbaariAjastin = new Timer();
232    Upgrade ostamassa;
233    Point digStart; // Huoneen sijainti, josta kaivuu aloitetaan.
234    bool digging = false;
235
236    GameObject digArrow;
237    GameObject digArrowHead;
238
239    IntMeter kultuuri = new IntMeter(1000, 0, 2000);
240
241    const int VAAKA_HUONEET = 12;
242    const int PYSTY_HUONEET = 8;
243
244    // Paljonko peliruudukko on siirtynyt origosta.
245    Vector huoneSiirtyma = new Vector(-200, 0);
246
247    public override void Begin()
248    {
249        //SetWindowSize(1024, 768);
250
251        ClearAll();
252        Kontrollit();
253        UlkoAsuRoskaa();
254        Kauppa();
255        Nuoli();
256
257        // Luodaan huoneet ruutuihin.
258        huoneet = new Room[VAAKA_HUONEET, PYSTY_HUONEET];
259        foreach (var paikka in RuutujenPaikat())
260        {
261            var huone = CreateRoom(paikka);
262            Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Pressed, () => RoomPressed(huone), null);
263            Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Released, () => RoomReleased(huone), null);
264            Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Pressed, AsetaPaivitys, "Asetetaan ostettu päivitys paikoilleen", huone);
265            Mouse.Listen(MouseButton.Right, ButtonState.Pressed, delegate { ostamassa = null; }, "Perutaan ostos");
266            Mouse.ListenOn(huone, MouseButton.Right, ButtonState.Pressed, PoistaPaivitys, "Poistetaan asetettu päivitys", huone);
267            huoneet[paikka.X, paikka.Y] = huone;
268        }
269
270        LuoSpawn();
271
272        Timer sykliAjastin = new Timer { Interval = 1.0 };
273        sykliAjastin.Timeout += Sykli;
274        sykliAjastin.Start();
275
276        barbaariAjastin.Timeout += LuoBarbaareja;
277        barbaariAjastin.Interval = 3;
278
279        Level.Width = 1300;
280        Camera.ZoomToLevel();
281    }
282
283    void Nuoli()
284    {
285        digArrow = new GameObject(5, 5);
286        digArrowHead = new GameObject(15, 15);
287        digArrowHead.Shape = Shape.Triangle;
288        digArrowHead.IsVisible = digArrow.IsVisible = false;
289        Add(digArrow, 3);
290        Add(digArrowHead, 3);
291    }
292
293    void UlkoAsuRoskaa()
294    {
295        Level.Background.Color = Color.Black;
296
297        kierrosIlmaisin = new Label("asd");
298        kierrosIlmaisin.TextColor = Color.White;
299        kierrosIlmaisin.Y = Screen.Top - 150;
300        Add(kierrosIlmaisin);
301        KierrosKaynnissa = KierrosKaynnissa; // Aiheuttaa labelin päivittymisen.
302
303        Label rahat = new Label();
304        rahat.BindTo(kultuuri);
305        rahat.Position = new Vector(Screen.Right - 200, Screen.Bottom + 50);
306        //rahat.Position = new Vector(Level.Right + Level.Width * 0.2, Level.Bottom + Level.Height * 0.1);
307        rahat.TextColor = Color.White;
308        rahat.IntFormatString = "Käytettävää kulttuuria: {0:D3}";
309        Add(rahat);
310    }
311
312    public void LopetaPeli()
313    {
314        ClearAll();
315        GameObject spurdo = new GameObject(Screen.Width, Screen.Height);
316        spurdo.Image = kultuuriKuvat[2];
317        Add(spurdo);
318
319        Label havisit = new Label("Hävisit muuten belin");
320        havisit.Color = Color.HotPink;
321        havisit.Size = new Vector(300, 300);
322        havisit.Position = new Vector(Level.Right - havisit.Width * 0.5, Level.Top - havisit.Height * 0.5);
323        Add(havisit);
324    }
325
326    void Kauppa()
327    {
328        for (int i = 0; i < kultuuriKuvat.Length; i++)
329        {
330            PushButton kuva = new PushButton(kultuuriKuvat[i]);
331            kuva.Size = new Vector(1, 1) * RUUDUN_KOKO;
332            kuva.X = Window.ClientBounds.Width / 2 - 200;
333            kuva.Y = Window.ClientBounds.Height / 2 - (100 + RUUDUN_KOKO * i);
334            //kuva.Position = new Vector((Level.Right + Level.Width * 0.05), (Level.Top - Level.Height * 0.25 - (i * RUUDUN_KOKO)));
335            //kuva.Position = new Vector(Window.ClientBounds.Right, 0);
336            Add(kuva);
337
338            int indeksi = i; // Alla oleva delegaatti vaatii uuden indeksi muuttujan toimiakseen.
339            kuva.Clicked += delegate
340            {
341                ostamassa = LuoKultuuriPaivitys(kultuuriKuvat[indeksi], hinnat[indeksi]);
342            };
343
344            Add(new Label
345            {
346                Position = kuva.Position + new Vector((RUUDUN_KOKO * 1.2), 0),
347                TextColor = Color.White,
348                Text = hinnat[i].ToString()
349            });
350        }
351
352        for (int i = 0; i < 1; i++)
353        {
354            PushButton kuva = new PushButton(ansaKuvat[i]);
355            kuva.Size = new Vector(1, 1) * RUUDUN_KOKO;
356            kuva.Color = Color.Gray;
357            kuva.X = Window.ClientBounds.Width / 2 - 200;
358            kuva.Y = Window.ClientBounds.Height / 2 - (100 + RUUDUN_KOKO * (kultuuriKuvat.Count() + i));
359            //kuva.Position = new Vector((Level.Right + Level.Width * 0.05), (Level.Top - Level.Height * 0.25 - ((kultuuriKuvat.Count() + i) * RUUDUN_KOKO)));
360            Add(kuva);
361
362            int indeksi = i;
363            kuva.Clicked += delegate
364            {
365                ostamassa = LuoAnsaPaivitys(ansaKuvat[ansaKuvat.Length - 1], ansaHinnat[indeksi]);
366            };
367
368            Add(new Label
369            {
370                Position = kuva.Position + new Vector((RUUDUN_KOKO * 1.2), 0),
371                TextColor = Color.White,
372                Text = ansaHinnat[i].ToString()
373            });
374        }
375    }
376
377    Upgrade LuoAnsaPaivitys(Image kuva, int hinta)
378    {
379        return new TrapUpgrade
380        {
381            Image = kuva,
382            Size = new Vector(0.5, 0.5) * RUUDUN_KOKO,
383            Price = hinta,
384            Animation = new Animation(ansaKuvat)
385        };
386    }
387
388    Upgrade LuoKultuuriPaivitys(Image kuva, int hinta)
389    {
390        return new CultureUpgrade
391        {
392            Image = kuva,
393            Size = new Vector(0.5, 0.5) * RUUDUN_KOKO,
394            Price = hinta
395        };
396    }
397
398    void LuoBarbaareja()
399    {
400        Barbaari barbaari = new Barbaari(RUUDUN_KOKO * 0.4, RUUDUN_KOKO * 0.4);
401        barbaari.Color = Color.Red;
402        barbaari.Position = spawn.Position;
403        barbaari.Animation = new Animation(vihuKuvat) { FPS = 10 };
404        barbaari.Animation.Start();
405        barbaari.Location = spawn.Location;
406        Add(barbaari);
407        barbaarit.Add(barbaari);
408
409        EtsiBarbaarinReitti(barbaari);
410    }
411
412    void EtsiBarbaarinReitti(Barbaari barbaari)
413    {
414        var kohteet = KultuuriHuoneidenPaikat();
415        barbaari.Kohde = kohteet[RandomGen.NextInt(kohteet.Count)];
416        barbaari.Reitti = FindPath(barbaari.Kohde, (barbaari.Location.Equals(spawn.Location)) ? spawn.Location : barbaari.Location);
417    }
418
419    public List<Point> KultuuriHuoneidenPaikat()
420    {
421        return RuutujenPaikat().Select(GetRoom).Where(r => r.Upgrade != null && r.Upgrade is CultureUpgrade).Select(r => r.Location).ToList();
422    }
423
424    void Sykli()
425    {
426        // Päivitetään huoneiden päivityksiä.
427        RuutujenPaikat().Select(GetRoom).Where(r => r.Upgrade != null).ToList().ForEach(r => r.Upgrade.SykliPaivitys());
428
429        // Päivitetään barbaareja.
430        foreach (var barbaari in barbaarit)
431        {
432            if (barbaari.Reitti.Count == 0)
433            {
434                EtsiBarbaarinReitti(barbaari);  //Etsitään uusi reitti poiston sijaan.
435                continue;
436            }
437
438            Point seuraavaPaikka = barbaari.Reitti[0];
439            barbaari.Reitti.RemoveAt(0);
440            Barbaari b = barbaari;
441            barbaari.MoveTo(huoneet[seuraavaPaikka.X, seuraavaPaikka.Y].Position, 100, () => SyklinPaatteeksi(b, seuraavaPaikka));
442        }
443
444        // Tarkistetaan onko barbaariaalto jo ohi.
445        if (KierrosKaynnissa && barbaarit.Count == 0 && barbaariAjastin.Times == barbaariAjastin.Times.MinValue)
446        {
447            KierrosKaynnissa = false;
448
449            // Annetaan pelaajalle kultuuripisteet.
450            foreach (var huone in KultuuriHuoneidenPaikat().Select(GetRoom))
451            {
452                CultureUpgrade upg = huone.Upgrade as CultureUpgrade;
453                if (upg == null)
454                    continue;
455
456                kultuuri.Value += upg.Culture;
457                Label ilmoitus = new Label("+" + upg.Culture);
458                ilmoitus.TextColor = Color.HotPink;
459                ilmoitus.Color = Color.Black;
460                ilmoitus.Position = Camera.WorldToScreen(huone.Position);
461                Add(ilmoitus);
462
463                double kohdeY = ilmoitus.Y + 50;
464                var liikutusAjastin = new Timer();
465                liikutusAjastin.Interval = 0.02;
466                liikutusAjastin.Timeout += delegate
467                {
468                    ilmoitus.Y += (kohdeY - ilmoitus.Y) * 0.05;
469                };
470                liikutusAjastin.Start();
471
472                ilmoitus.LifetimeLeft = TimeSpan.FromSeconds(2.0);
473                ilmoitus.Destroyed += liikutusAjastin.Stop;
474            }
475        }
476    }
477
478    void SyklinPaatteeksi(Barbaari barbaari, Point uusiPaikka)
479    {
480        // Barbaari saapui juuri uusiPaikka kohdassa olevaan huoneeseen.
481        // Tässä pitäisi katsoa mitä huoneessa tapahtuu.
482        barbaari.Location = uusiPaikka;
483
484        Room huone = huoneet[uusiPaikka.X, uusiPaikka.Y];
485
486        if (huone.Upgrade != null)
487        {
488            huone.Upgrade.Invasion(this, barbaari, huone);
489        }
490    }
491
492    void Kontrollit()
493    {
494        IsMouseVisible = true;
495        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, "Lopeta peli");
496        Keyboard.Listen(Key.F1, ButtonState.Pressed, Begin, null);
497
498        Keyboard.Listen(Key.Space, ButtonState.Pressed, SeuraavaAalto, "Anna kivan barbaariaallon tulla");
499    }
500
501    void SeuraavaAalto()       
502    {
503        if (KultuuriHuoneidenPaikat().Count == 0 || KierrosKaynnissa) return;
504
505        barbaariAjastin.Start(barbaariMaara);
506        barbaariMaara += 2;
507        KierrosKaynnissa = true;
508    }
509
510    void LuoSpawn()
511    {
512        spawn = huoneet[(int)(huoneet.GetLength(0) * 0.5), 0];
513        spawn.Dug = true;
514
515        Direction oviSuunta = Direction.Down;
516        spawn.Walls[oviSuunta].Image = reikaSeinaKuva;
517
518        spawn.Upgrade = new TrapUpgrade();      //TODO: Parempi tapa varmistaa, että spawniin ei pysty rakentamaan mitään? Oma upgradetyyppi?
519        TrapUpgrade upg = spawn.Upgrade as TrapUpgrade;
520        upg.LatausMittari = new IntMeter(0, 0, 0);
521
522        Light valo = new Light();
523        valo.Position = spawn.Position;
524        valo.Intensity = 1;
525        valo.Distance = 40;
526        Add(valo);
527    }
528
529    void RoomPressed(Room huone)
530    {
531        digStart = huone.Location;
532        digging = true;
533        digArrowHead.IsVisible = digArrow.IsVisible = true;
534    }
535
536    void RoomReleased(Room kohdeHuone)
537    {
538        digging = false;
539        digArrowHead.IsVisible = digArrow.IsVisible = false;
540        if (!CanDig()) return;
541
542        int dx = kohdeHuone.Location.X - digStart.X;
543        int dy = kohdeHuone.Location.Y - digStart.Y;
544        Point[] kaivettavatPaikat = RuudutSuoralta(digStart, dx, dy).ToArray();
545        for (int i = 0; i < kaivettavatPaikat.Length - 1; i++)
546        {
547            Dig(GetRoom(kaivettavatPaikat[i]), GetRoom(kaivettavatPaikat[i + 1]));
548        }
549
550        // Päivitetään huoneiden kultuuri-infot.
551        PaivitaHuoneidenKultuurit();
552    }
553
554    void Dig(Room alku, Room kohde)
555    {
556        // Hienot partikkeliefektit.
557        if (!alku.Dug)
558            LuoKiviPartikkelit(alku.Position);
559        if (!kohde.Dug)
560            LuoKiviPartikkelit(kohde.Position);
561
562        // Merkataan huoneet kaivetuksi.
563        alku.Dug = kohde.Dug = true;
564
565        // Reiät seinään.
566        Direction oviSuunta = (kohde.Position - alku.Position).Angle.MainDirection;
567        Direction toinenOviSuunta = Direction.Inverse(oviSuunta);
568        alku.Walls[oviSuunta].Image = reikaSeinaKuva;
569        kohde.Walls[toinenOviSuunta].Image = reikaSeinaKuva;
570    }
571
572    Room CreateRoom(Point paikka)
573    {
574        Room huone = new Room(paikka);
575        huone.Image = lattiaKuva;
576        huone.Position = new Vector(paikka.X - huoneet.GetLength(0) / 2, paikka.Y - huoneet.GetLength(1) / 2) * RUUDUN_KOKO;
577        huone.Position += huoneSiirtyma;
578        foreach (var suunta in Suunnat())
579            huone.Walls[suunta] = CreateWall(huone.Position, suunta);
580        Add(huone, -2);
581        huone.Roof = new GameObject(RUUDUN_KOKO, RUUDUN_KOKO);
582        huone.Roof.Image = kiviKuva;
583        huone.Roof.Position = huone.Position;
584        Add(huone.Roof, 1);
585
586        //Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Pressed, AsetaPaivitys, "Asetetaan ostettu päivitys paikoilleen", huone);
587        //Mouse.Listen(MouseButton.Right, ButtonState.Pressed, delegate { ostamassa = null; }, "Perutaan ostos");
588        //Mouse.ListenOn(huone, MouseButton.Right, ButtonState.Pressed, PoistaPaivitys, "Poistetaan asetettu päivitys", huone);
589
590        return huone;
591    }
592
593    private void PoistaPaivitys(Room huone)
594    {
595        if (huone.Upgrade != null)
596        {
597            kultuuri.Value += (int)(huone.Upgrade.Price * 0.5);
598            huone.Upgrade.Destroy();
599            huone.Upgrade = null;
600        }
601    }
602
603    void AsetaPaivitys(Room huone)
604    {
605        if (ostamassa != null && huone.Dug && kultuuri.Value >= ostamassa.Price && huone.Upgrade == null) //Varmistetaan, että kahta päivitystä ei laiteta päällekäin
606        {
607            kultuuri.Value -= ostamassa.Price;
608
609            // Lisätään päivitys huoneeseen.
610            huone.Upgrade = ostamassa;
611            Add(huone.Upgrade, -1);
612            huone.Upgrade.Position = huone.Position;
613            huone.Upgrade.Built(this);
614
615            ostamassa = null;
616            PaivitaHuoneenKultuuri(huone);
617        }
618    }
619
620    void PaivitaHuoneidenKultuurit()
621    {
622        RuutujenPaikat().Select(GetRoom).ToList().ForEach(PaivitaHuoneenKultuuri); // :D ;___;; MIKSI <- koska pystyn
623    }
624
625    void PaivitaHuoneenKultuuri(Room room)
626    {
627        if (room != null && room.Upgrade != null && room.Upgrade is CultureUpgrade)
628        {
629            var upg = room.Upgrade as CultureUpgrade;
630
631            List<Point> polku = FindPath(room.Location, spawn.Location);
632            upg.Culture.Value = Math.Max(0, 150 - 5 * polku.Count);
633        }
634    }
635
636    GameObject CreateWall(Vector paikka, Direction suunta)
637    {
638        GameObject wall = new GameObject(RUUDUN_KOKO + 2, RUUDUN_KOKO + 2);
639        wall.Position = paikka;
640        wall.Image = seinaKuva;
641        wall.Angle = suunta.Angle;
642        Add(wall, 0);
643        return wall;
644    }
645
646    bool CanDig()
647    {
648        Room kohdeHuone = GetRoom(MuunnaJypelista(Mouse.PositionOnWorld));
649        if (kohdeHuone == null || kierrosKaynnissa)
650        {
651            return false;
652        }
653
654        int dx = Math.Abs(kohdeHuone.Location.X - digStart.X);
655        int dy = Math.Abs(kohdeHuone.Location.Y - digStart.Y);
656        return (dx > 0 && dy == 0) || (dy > 0 && dx == 0);
657    }
658
659    #region Reitinlöytö
660
661    List<Point> FindPath(Point alku, Point loppu)
662    {
663        if (GetRoom(alku) == null || GetRoom(loppu) == null)
664            return new List<Point>();
665
666        bool[,] walkable = new bool[huoneet.GetLength(0), huoneet.GetLength(1)];
667        foreach (var paikka in RuutujenPaikat())
668        {
669            walkable[paikka.X, paikka.Y] = huoneet[paikka.X, paikka.Y].Dug;
670        }
671        var finder = new AStar.PathFinder(new AStar.SearchParameters(loppu, alku, walkable), OviTarkistus);
672        return finder.FindPath();
673    }
674
675    bool OviTarkistus(Point a, Point b)
676    {
677        Room ra = GetRoom(a);
678        Room rb = GetRoom(b);
679        Direction suunta = (new Vector(b.X, b.Y) - new Vector(a.X, a.Y)).Angle.MainDirection;
680        if (ra != null && rb != null)
681        {
682            return ra.Walls[suunta].Image == reikaSeinaKuva && rb.Walls[Direction.Inverse(suunta)].Image == reikaSeinaKuva;
683        }
684        return false;
685    }
686
687    #endregion
688
689    #region Extra Juttuja
690
691    IEnumerable<Direction> Suunnat()
692    {
693        yield return Direction.Left;
694        yield return Direction.Right;
695        yield return Direction.Up;
696        yield return Direction.Down;
697    }
698
699    IEnumerable<Point> RuutujenPaikat()
700    {
701        return from y in Enumerable.Range(0, huoneet.GetLength(1))
702               from x in Enumerable.Range(0, huoneet.GetLength(0))
703               select new Point(x, y);
704    }
705
706    /// <summary>
707    /// Palauttaa ruutuja suoralta pätkältä dx ja dy verran alkaen pisteestä "alku".
708    /// dx tai dy pitää olla nolla.
709    /// </summary>
710    IEnumerable<Point> RuudutSuoralta(Point alku, int dx, int dy)
711    {
712        if (dx != 0)
713        {
714            for (int i = 0; i < Math.Abs(dx) + 1; i++)
715            {
716                yield return new Point(alku.X + i * Math.Sign(dx), alku.Y);
717            }
718            yield break;
719        }
720        if (dy != 0)
721        {
722            for (int i = 0; i < Math.Abs(dy) + 1; i++)
723            {
724                yield return new Point(alku.X, alku.Y + i * Math.Sign(dy));
725            }
726        }
727    }
728
729    Room GetRoom(Point paikka)
730    {
731        if (paikka.X >= 0 && paikka.X < huoneet.GetLength(0) && paikka.Y >= 0 && paikka.Y < huoneet.GetLength(1))
732        {
733            return huoneet[paikka.X, paikka.Y];
734        }
735        return null;
736    }
737
738    /// <summary>
739    /// Muuntaa Jypeli-koordinaatin peliruudukon koordinaatiksi.
740    /// </summary>
741    Point MuunnaJypelista(Vector paikka)
742    {
743        Vector siirrettyOrigo = (paikka - huoneSiirtyma) + RUUDUN_KOKO * (0.5 * new Vector(huoneet.GetLength(0), huoneet.GetLength(1)) + new Vector(0.5, 0.5));
744        Vector wtf = new Vector(siirrettyOrigo.X < 0 ? -1 : 0, siirrettyOrigo.Y < 0 ? -1 : 0);
745        Vector valmis = wtf + siirrettyOrigo / RUUDUN_KOKO;
746        return new Point((int)valmis.X, (int)valmis.Y);
747    }
748
749    public void LuoLentavaPartikkeli(Vector alkupaikka, Image kuva, double koko, int maara, bool veri = false)
750    {
751        // Feikki 3D partikkeli juttu.
752        // Heittää ilmaan GameObjekteja joiden alla on varjo.
753
754        // VAROITUS: SISÄLTÄÄ JÄRKYTTÄVÄÄ KOODIA
755
756        for (int i = 0; i < maara; i++)
757        {
758            GameObject partikkeli = new GameObject(koko, koko);
759            partikkeli.Image = kuva;
760            partikkeli.Position = alkupaikka + RandomGen.NextVector(0.0, RUUDUN_KOKO * 0.4);
761            Add(partikkeli, 3);
762
763            GameObject varjo = new GameObject(koko, koko / 2.0);
764            varjo.Position = partikkeli.Position;
765            varjo.Shape = Shape.Circle;
766            varjo.Color = Color.Lerp(Color.Black, Color.Transparent, 0.5);
767            Add(varjo, 2);
768
769            Vector paikka = partikkeli.Position;
770            Vector nopeus = RandomGen.NextVector(0.2, 3.0);
771            nopeus.Y *= 0.3;
772            double g = -0.2; // painovoima
773            double z = 0.0; // sijainti z-akselilla
774            double vz = RandomGen.NextDouble(3.5, 4.5); // nopeus z-akselilla
775            double angularVelocity = RandomGen.NextDouble(-1.0, 1.0) * 8;
776
777            var verenLuontiAjastin = veri ? new Timer() : null;
778
779            var ajastin = new Timer();
780            ajastin.Interval = 0.02;
781            ajastin.Timeout += delegate
782            {
783                vz += g;
784                z += vz;
785                paikka += nopeus;
786                partikkeli.Position = paikka + new Vector(0.0, 1.0) * z;
787                partikkeli.Angle += Angle.FromDegrees(angularVelocity);
788                varjo.Position = paikka;
789
790                if (z < 0.0)
791                {
792                    ajastin.Stop();
793                    partikkeli.Destroy();
794                    varjo.Destroy();
795                    if (verenLuontiAjastin != null)
796                        verenLuontiAjastin.Stop();
797                }
798            };
799            ajastin.Start();
800
801            if (verenLuontiAjastin != null)
802            {
803                verenLuontiAjastin.Interval = 0.1;
804                verenLuontiAjastin.Timeout += delegate
805                {
806                    GameObject veriPartikkeli = new GameObject(3, 3);
807                    veriPartikkeli.Color = Color.DarkRed;
808                    Add(veriPartikkeli, 2);
809
810                    Vector veriPaikka = paikka;
811                    double veriZ = z;
812                    double veriVz = 0.0;
813
814                    var veriPaivitysAjastin = new Timer();
815                    veriPaivitysAjastin.Interval = 0.02;
816                    veriPaivitysAjastin.Timeout += delegate
817                    {
818                        veriVz += g;
819                        veriZ += veriVz;
820                        veriPartikkeli.Position = veriPaikka + new Vector(0.0, 1.0) * veriZ;
821
822                        if (veriZ < 0.0)
823                        {
824                            veriPaivitysAjastin.Stop();
825                            veriPartikkeli.Destroy();
826                        }
827                    };
828                    veriPaivitysAjastin.Start();
829                };
830                verenLuontiAjastin.Start();
831            }
832        }
833    }
834
835    void LuoKiviPartikkelit(Vector alkupaikka)
836    {
837        LuoLentavaPartikkeli(alkupaikka, partikkeliKuva, 25, 6);
838    }
839
840    public void Splatter(Vector alkupaikka)
841    {
842        LuoLentavaPartikkeli(alkupaikka, taideVeri, 8, 10, true);
843    }
844
845    protected override void Update(Time time)
846    {
847        if (digging)
848        {
849            Color vari = CanDig() ? Color.White : Color.Red;
850            Vector alku = huoneet[digStart.X, digStart.Y].Position;
851            Vector loppu = Mouse.PositionOnWorld;
852            Vector suunta = loppu - alku;
853            double pituus = suunta.Magnitude;
854            if (pituus <= 2) pituus = 2;
855
856            digArrow.Color = vari;
857            digArrow.Position = alku + suunta * 0.5;
858            digArrow.Angle = suunta.Angle;
859            digArrow.Width = pituus;
860
861            digArrowHead.Color = vari;
862            digArrowHead.Position = alku + suunta;
863            digArrowHead.Angle = suunta.Angle - Angle.FromDegrees(90);
864        }
865
866        base.Update(time);
867    }
868
869    /*
870    protected override void Paint(Canvas canvas)
871    {
872        canvas.BrushColor = Color.Purple;
873
874        var points = FindPath(new Point(6, 0), MuunnaJypelista(Mouse.PositionOnWorld));
875        for (int i = 0; i < points.Count - 1; i++)
876        {
877            Vector v = huoneSiirtyma + new Vector(points[i].X - huoneet.GetLength(0) / 2, points[i].Y - huoneet.GetLength(1) / 2) * RUUDUN_KOKO;
878            Vector v2 = huoneSiirtyma + new Vector(points[i + 1].X - huoneet.GetLength(0) / 2, points[i + 1].Y - huoneet.GetLength(1) / 2) * RUUDUN_KOKO;
879            canvas.DrawLine(v, v2);
880        }
881
882        base.Paint(canvas);
883    }
884    */
885
886    #endregion
887}
Note: See TracBrowser for help on using the repository browser.