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

Revision 6113, 36.6 KB checked in by sieerinn, 6 years ago (diff)

Kaikenlaista pientä säätöä.

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