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

Revision 6045, 27.9 KB checked in by sieerinn, 4 years ago (diff)

Toimii paremmin eri kokoisilla ikkunoilla nyt.

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