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

Revision 6097, 32.3 KB checked in by empaheik, 4 years ago (diff)

Ansat tekevät eri määrän vahinkoa.

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