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

Revision 6106, 34.1 KB checked in by sieerinn, 5 years ago (diff)

Ääntä.

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