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

Revision 6109, 34.9 KB checked in by empaheik, 8 years ago (diff)
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    private Image[] loppuKuvat = LoadImages2(1, 35, "break/b{0:0000}");
234    #endregion
235
236    private SoundEffect[] hajotusAanet = { LoadSoundEffect("fountainbreak"), LoadSoundEffect("boom"), LoadSoundEffect("piano2") };
237
238    int[] hinnat = { 75, 200, 300, 100 };
239    int[] vahingot = { 1, 2 };
240    int[] ansaHinnat = { 300, 600 };
241    int[] kultuuriTuotot = { 100, 200, 400 };
242    private int barbaariMaara = 2;
243
244    private Label kaivuuHintaLabel;
245    private Label kierrosIlmaisin;
246    //private bool kierrosKaynnissa;
247    private int kierros;
248
249    public int KierrosKaynnissa
250    {
251        get
252        {
253            return kierros;
254        }
255        set
256        {
257            kierros = value;
258            kierrosIlmaisin.Text = "Vaihe: " + (kierros % 2 == 0 ? "Barbaari-invaasio" : "Rakennusvaihe");
259        }
260    }
261
262    Room[,] huoneet;
263    //public List<Room> kohteet = new List<Room>();
264    public List<Barbaari> barbaarit;
265    Room spawn;
266    Timer barbaariAjastin;
267    Timer sykliAjastin;
268    Upgrade ostamassa;
269    Point digStart; // Huoneen sijainti, josta kaivuu aloitetaan.
270
271    private bool digging = false;
272
273    public bool Digging
274    {
275        get
276        {
277            return digging;
278        }
279        set
280        {
281            digging = value;
282            kaivuuHintaLabel.IsVisible = Digging;
283        }
284    }
285
286    GameObject digArrow;
287    GameObject digArrowHead;
288
289    IntMeter kultuuri = new IntMeter(0, 0, 2000);
290
291    const int MASSI = 2000;
292    const int VAAKA_HUONEET = 12;
293    const int PYSTY_HUONEET = 8;
294    const int HUONE_KAIVUU_HINTA = 50;
295
296    // Paljonko peliruudukko on siirtynyt origosta.
297    Vector huoneSiirtyma = new Vector(-200, 0);
298
299    private MainMenu menu;
300
301    public override void Begin()
302    {
303        ClearAll();
304
305        kultuuri.Value = MASSI;
306        kierros = 0;
307        barbaariAjastin = new Timer();
308        barbaarit = new List<Barbaari>();
309
310        SmoothTextures = false;
311        IsMouseVisible = true;
312
313        //SetWindowSize(1024, 768); // Riippuu Jypelin versiosta.
314        Window.Width = 1024;
315        Window.Height = 768;
316
317        ansaKuvat = new Image[] { piikkiAnsaKuvat[0], murskausAnsaKuvat[0] };
318        ansaAnimaatiot.Add(new Animation(piikkiAnsaKuvat));
319        ansaAnimaatiot.Add(new Animation(murskausAnsaKuvat));
320        menu = new MainMenu(this, "New game", "Highscores", "Help", "Quit");
321        menu.Painikkeet[0].Clicked += delegate
322        {
323            AloitaPeli();
324            menu = null;
325        };
326        menu.Painikkeet[3].Clicked += Exit;
327    }
328
329    void AloitaPeli()
330    {
331        ClearAll();
332        MediaPlayer.Play("In_The_Dark_Flashes");
333        Kontrollit();
334        UlkoAsuRoskaa();
335        Kauppa();
336        Nuoli();
337
338        // Luodaan huoneet ruutuihin.
339        huoneet = new Room[VAAKA_HUONEET, PYSTY_HUONEET];
340        foreach (var paikka in RuutujenPaikat())
341        {
342            var huone = CreateRoom(paikka);
343            Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Pressed, () => RoomPressed(huone), null);
344            Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Released, () => RoomReleased(huone), null);
345            Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Pressed, AsetaPaivitys, "Asetetaan ostettu päivitys paikoilleen", huone);
346            Mouse.Listen(MouseButton.Right, ButtonState.Pressed, delegate { ostamassa = null; }, "Perutaan ostos");
347            Mouse.ListenOn(huone, MouseButton.Right, ButtonState.Pressed, PoistaPaivitys, "Poistetaan asetettu päivitys", huone);
348            huoneet[paikka.X, paikka.Y] = huone;
349        }
350
351        LuoSpawn();
352
353        sykliAjastin = new Timer { Interval = 1.0 };
354        sykliAjastin.Timeout += Sykli;
355        sykliAjastin.Start();
356
357        barbaariAjastin.Timeout += LuoBarbaareja;
358        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ä
359
360        Level.Width = 1300;
361        Camera.ZoomToLevel();
362    }
363
364    void Nuoli()
365    {
366        digArrow = new GameObject(5, 5);
367        digArrowHead = new GameObject(15, 15);
368        digArrowHead.Shape = Shape.Triangle;
369        digArrowHead.IsVisible = digArrow.IsVisible = false;
370        Add(digArrow, 3);
371        Add(digArrowHead, 3);
372    }
373
374    void UlkoAsuRoskaa()
375    {
376        Level.Background.Color = Color.Black;
377
378        kierrosIlmaisin = new Label("asd");
379        kierrosIlmaisin.TextColor = Color.White;
380        kierrosIlmaisin.Y = Screen.Top - 150;
381        Add(kierrosIlmaisin);
382        KierrosKaynnissa = KierrosKaynnissa; // Aiheuttaa labelin päivittymisen.
383
384        kaivuuHintaLabel = new Label("0");
385        kaivuuHintaLabel.IsVisible = false;
386        kaivuuHintaLabel.TextColor = Color.HotPink;
387        kaivuuHintaLabel.Color = Color.Black;
388        Add(kaivuuHintaLabel);
389
390        Label rahat = new Label();
391        rahat.BindTo(kultuuri);
392        rahat.Position = new Vector(Screen.Right - 200, Screen.Bottom + 50);
393        //rahat.Position = new Vector(Level.Right + Level.Width * 0.2, Level.Bottom + Level.Height * 0.1);
394        rahat.TextColor = Color.White;
395        rahat.IntFormatString = "Käytettävää kulttuuria: {0:D3}";
396        Add(rahat);
397    }
398
399    public void LopetaPeli()
400    {
401        ClearAll();
402        Level.Background.Color = Color.Black;
403        var patsas = new GameObject(400, 300);
404        patsas.Image = loppuKuvat[0];
405        patsas.Animation = new Animation(loppuKuvat) { FPS = 20, StopOnLastFrame = true };
406        Add(patsas);
407
408        Timer.SingleShot(3.0, delegate
409        {
410            patsas.Animation.Start(1);
411            hajotusAanet[1].Play();
412        });
413
414        Label havisit = new Label("Hävisit muuten belin");
415        havisit.TextColor = Color.Black;
416        havisit.TextScale *= 3;
417        havisit.Top = Screen.Top - 30.0;
418        Add(havisit, 2);
419
420        const double fadeAika = 5.0;
421        var fadeAjastin = new Timer();
422        fadeAjastin.Interval = 0.02;
423        fadeAjastin.Timeout += delegate
424        {
425            havisit.TextColor = Color.Lerp(Color.Black, Color.White, fadeAjastin.SecondCounter.Value / fadeAika);
426            if (fadeAjastin.SecondCounter.Value > fadeAika)
427            {
428                fadeAjastin.Stop();
429            }
430        };
431        fadeAjastin.Start();
432
433        Keyboard.Listen(Key.Escape, ButtonState.Pressed, delegate { ClearAll(); Begin(); }, null);
434    }
435
436    void Kauppa()
437    {
438        for (int i = 0; i < kultuuriKuvat.Length; i++)
439        {
440            PushButton kuva = new PushButton(kultuuriKuvat[i][0]);
441            kuva.Size = new Vector(1, 1) * RUUDUN_KOKO;
442            kuva.X = Window.ClientBounds.Width / 2 - 200;
443            kuva.Y = Window.ClientBounds.Height / 2 - (100 + RUUDUN_KOKO * i);
444            //kuva.Position = new Vector((Level.Right + Level.Width * 0.05), (Level.Top - Level.Height * 0.25 - (i * RUUDUN_KOKO)));
445            //kuva.Position = new Vector(Window.ClientBounds.Right, 0);
446            Add(kuva);
447
448            int indeksi = i; // Alla oleva delegaatti vaatii uuden indeksi muuttujan toimiakseen.
449            kuva.Clicked += delegate
450            {
451                ostamassa = LuoKultuuriPaivitys(kultuuriKuvat[indeksi], hinnat[indeksi], kultuuriTuotot[indeksi], hajotusAanet[indeksi]);   // TODO: tuotto[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 = hinnat[i].ToString()
459            });
460        }
461
462        for (int i = 0; i < ansaKuvat.Length; i++)
463        {
464            PushButton kuva = new PushButton(ansaKuvat[i]);
465            kuva.Size = new Vector(1, 1) * RUUDUN_KOKO;
466            kuva.Color = Color.Gray;
467            kuva.X = Window.ClientBounds.Width / 2 - 200;
468            kuva.Y = Window.ClientBounds.Height / 2 - (100 + RUUDUN_KOKO * (kultuuriKuvat.Count() + i));
469            //kuva.Position = new Vector((Level.Right + Level.Width * 0.05), (Level.Top - Level.Height * 0.25 - ((kultuuriKuvat.Count() + i) * RUUDUN_KOKO)));
470            Add(kuva);
471
472            int indeksi = i;
473            kuva.Clicked += delegate
474            {
475                ostamassa = LuoAnsaPaivitys(ansaKuvat[indeksi], ansaHinnat[indeksi], ansaAnimaatiot[indeksi], vahingot[indeksi]);
476            };
477
478            Add(new Label
479            {
480                Position = kuva.Position + new Vector((RUUDUN_KOKO * 1.2), 0),
481                TextColor = Color.White,
482                Text = ansaHinnat[i].ToString()
483            });
484        }
485    }
486
487    private void LuoAnsaHuoneenPainike(Image image, int hinta, Animation animation, int paikka, int vahinko)
488    {
489        PushButton kuva = new PushButton(image);
490        kuva.Size = new Vector(1, 1) * RUUDUN_KOKO;
491        kuva.Color = Color.Gray;
492        kuva.X = Window.ClientBounds.Width / 2 - 200;
493        kuva.Y = Window.ClientBounds.Height / 2 - (100 + RUUDUN_KOKO * (kultuuriKuvat.Count() + paikka));
494        //kuva.Position = new Vector((Level.Right + Level.Width * 0.05), (Level.Top - Level.Height * 0.25 - ((kultuuriKuvat.Count() + i) * RUUDUN_KOKO)));
495        Add(kuva);
496
497        kuva.Clicked += delegate
498        {
499            ostamassa = LuoAnsaPaivitys(image, hinta, animation, vahinko);
500        };
501
502        Add(new Label
503        {
504            Position = kuva.Position + new Vector((RUUDUN_KOKO * 1.2), 0),
505            TextColor = Color.White,
506            Text = hinta.ToString()
507        });
508    }
509
510
511
512    Upgrade LuoAnsaPaivitys(Image kuva, int hinta, Animation animaatio, int vahinko)
513    {
514        return new TrapUpgrade
515        {
516            Image = kuva,
517            Size = new Vector(0.5, 0.5) * RUUDUN_KOKO,
518            Price = hinta,
519            Damage = vahinko,
520            Animation = new Animation(animaatio)
521        };
522    }
523
524    Upgrade LuoKultuuriPaivitys(Image[] kuvat, int hinta, int kultuuriMaara, SoundEffect hajotusAani)
525    {
526        var upg = new CultureUpgrade();
527        upg.HajotusAani = hajotusAani;
528        upg.Image = kuvat[0];
529        upg.Size = new Vector(0.7, 0.7)*RUUDUN_KOKO;
530        upg.Price = hinta;
531        upg.Max = kultuuriMaara;
532        upg.Animation = new Animation(kuvat) { FPS = 10 };
533        upg.Animation.Start();
534        return upg;
535    }
536
537    void LuoBarbaareja()
538    {
539        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));
540        barbaari.Tenacity.LowerLimit += delegate
541        {
542            barbaarit.Remove(barbaari);
543            barbaari.Destroy();
544        };
545        //Barbaari barbaari = new Barbaari(RUUDUN_KOKO * 0.4, RUUDUN_KOKO * 0.4, 0);
546        barbaari.Color = Color.Red;
547        barbaari.Position = spawn.Position;
548        barbaari.Location = spawn.Location;
549        //barbaari.Animation = new Animation(vihuKuvat) { FPS = 10 };
550        barbaari.Animation.Start();
551        Add(barbaari);
552        barbaarit.Add(barbaari);
553
554        EtsiBarbaarinReitti(barbaari);
555    }
556
557    void EtsiBarbaarinReitti(Barbaari barbaari)
558    {
559        var kohteet = KultuuriHuoneidenPaikat();
560        barbaari.Kohde = kohteet[RandomGen.NextInt(kohteet.Count)];
561        barbaari.Reitti = FindPath(barbaari.Kohde, (barbaari.Location.Equals(spawn.Location)) ? spawn.Location : barbaari.Location);
562    }
563
564    public List<Point> KultuuriHuoneidenPaikat()
565    {
566        return RuutujenPaikat().Select(GetRoom).Where(r => r.Upgrade != null && r.Upgrade is CultureUpgrade).Select(r => r.Location).ToList();
567    }
568
569    void Sykli()
570    {
571        // Päivitetään huoneiden päivityksiä.
572        RuutujenPaikat().Select(GetRoom).Where(r => r.Upgrade != null).ToList().ForEach(r => r.Upgrade.SykliPaivitys());
573
574        // Päivitetään barbaareja.
575        foreach (var barbaari in barbaarit)
576        {
577            if (barbaari.Reitti.Count == 0)
578            {
579                EtsiBarbaarinReitti(barbaari);  //Etsitään uusi reitti poiston sijaan.
580                continue;
581            }
582
583            Point seuraavaPaikka = barbaari.Reitti[0];
584            barbaari.Reitti.RemoveAt(0);
585            Barbaari b = barbaari;
586            barbaari.MoveTo(huoneet[seuraavaPaikka.X, seuraavaPaikka.Y].Position, 100, () => SyklinPaatteeksi(b, seuraavaPaikka));
587        }
588
589        // Tarkistetaan onko barbaariaalto jo ohi.
590        if (KierrosKaynnissa % 2 == 0 && barbaarit.Count == 0 && barbaariAjastin.Times == barbaariAjastin.Times.MinValue)
591        {
592            KierrosKaynnissa++;
593
594            // Annetaan pelaajalle kultuuripisteet.
595            foreach (var huone in KultuuriHuoneidenPaikat().Select(GetRoom))
596            {
597                CultureUpgrade upg = huone.Upgrade as CultureUpgrade;
598                if (upg == null)
599                    continue;
600
601                kultuuri.Value += upg.Culture;
602                Label ilmoitus = new Label("+" + upg.Culture);
603                ilmoitus.TextColor = Color.HotPink;
604                ilmoitus.Color = Color.Black;
605                ilmoitus.Position = Camera.WorldToScreen(huone.Position);
606                Add(ilmoitus);
607
608                double kohdeY = ilmoitus.Y + 50;
609                var liikutusAjastin = new Timer();
610                liikutusAjastin.Interval = 0.02;
611                liikutusAjastin.Timeout += delegate
612                {
613                    ilmoitus.Y += (kohdeY - ilmoitus.Y) * 0.05;
614                };
615                liikutusAjastin.Start();
616
617                ilmoitus.LifetimeLeft = TimeSpan.FromSeconds(2.0);
618                ilmoitus.Destroyed += liikutusAjastin.Stop;
619            }
620        }
621    }
622
623    void SyklinPaatteeksi(Barbaari barbaari, Point uusiPaikka)
624    {
625        // Barbaari saapui juuri uusiPaikka kohdassa olevaan huoneeseen.
626        // Tässä pitäisi katsoa mitä huoneessa tapahtuu.
627        barbaari.Location = uusiPaikka;
628
629        Room huone = huoneet[uusiPaikka.X, uusiPaikka.Y];
630
631        if (huone.Upgrade != null)
632        {
633            huone.Upgrade.Invasion(this, barbaari, huone);
634        }
635    }
636
637    void Kontrollit()
638    {
639        IsMouseVisible = true;
640        //Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, "Näytä valikko");
641        //Keyboard.Listen(Key.F1, ButtonState.Pressed, Begin, null);
642        Keyboard.Listen(Key.Escape, ButtonState.Pressed, delegate { ClearAll(); Begin(); }, "Aloita uudestaan");    //Ei toimi vielä
643
644        Keyboard.Listen(Key.Space, ButtonState.Pressed, SeuraavaAalto, "Anna kivan barbaariaallon tulla");
645    }
646
647    void SeuraavaAalto()
648    {
649        if (KultuuriHuoneidenPaikat().Count == 0 || KierrosKaynnissa % 2 == 0) return;
650
651        barbaariAjastin.Interval = RandomGen.NextInt((int)sykliAjastin.Interval, 3);
652        barbaariAjastin.Start(barbaariMaara);
653        barbaariMaara = RandomGen.NextInt((int)(1 + kierros * 0.20), kierros);
654        KierrosKaynnissa++;
655    }
656
657    void LuoSpawn()
658    {
659        spawn = huoneet[(int)(huoneet.GetLength(0) * 0.5), 0];
660        spawn.Dug = true;
661
662        Direction oviSuunta = Direction.Down;
663        spawn.Walls[oviSuunta].Image = reikaSeinaKuva;
664
665        Light valo = new Light();
666        valo.Position = spawn.Position;
667        valo.Intensity = 1;
668        valo.Distance = 40;
669        Add(valo);
670    }
671
672    void RoomPressed(Room huone)
673    {
674        digStart = huone.Location;
675        Digging = true;
676        digArrowHead.IsVisible = digArrow.IsVisible = true;
677    }
678
679    void RoomReleased(Room kohdeHuone)
680    {
681        Digging = false;
682        digArrowHead.IsVisible = digArrow.IsVisible = false;
683        if (!CanDig()) return;
684
685        int dx = kohdeHuone.Location.X - digStart.X;
686        int dy = kohdeHuone.Location.Y - digStart.Y;
687        Point[] kaivettavatPaikat = RuudutSuoralta(digStart, dx, dy).ToArray();
688        for (int i = 0; i < kaivettavatPaikat.Length - 1; i++)
689        {
690            Dig(GetRoom(kaivettavatPaikat[i]), GetRoom(kaivettavatPaikat[i + 1]));
691        }
692
693        // Päivitetään huoneiden kultuuri-infot.
694        PaivitaHuoneidenKultuurit();
695    }
696
697    void Dig(Room alku, Room kohde)
698    {
699        // Hienot partikkeliefektit.
700        if (!alku.Dug)
701            LuoKiviPartikkelit(alku.Position);
702        if (!kohde.Dug)
703            LuoKiviPartikkelit(kohde.Position);
704
705        // Merkataan huoneet kaivetuksi ja maksetaan siitä kivasti.
706        alku.Dug = kohde.Dug = true;
707        kultuuri.Value -= HUONE_KAIVUU_HINTA;
708
709        // Reiät seinään.
710        Direction oviSuunta = (kohde.Position - alku.Position).Angle.MainDirection;
711        Direction toinenOviSuunta = Direction.Inverse(oviSuunta);
712        alku.Walls[oviSuunta].Image = reikaSeinaKuva;
713        kohde.Walls[toinenOviSuunta].Image = reikaSeinaKuva;
714    }
715
716    Room CreateRoom(Point paikka)
717    {
718        Room huone = new Room(paikka);
719        huone.Image = lattiaKuva;
720        huone.Position = new Vector(paikka.X - huoneet.GetLength(0) / 2, paikka.Y - huoneet.GetLength(1) / 2) * RUUDUN_KOKO;
721        huone.Position += huoneSiirtyma;
722        foreach (var suunta in Suunnat())
723            huone.Walls[suunta] = CreateWall(huone.Position, suunta);
724        Add(huone, -2);
725        huone.Roof = new GameObject(RUUDUN_KOKO, RUUDUN_KOKO);
726        huone.Roof.Image = kiviKuva;
727        huone.Roof.Position = huone.Position;
728        Add(huone.Roof, 1);
729
730        //Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Pressed, AsetaPaivitys, "Asetetaan ostettu päivitys paikoilleen", huone);
731        //Mouse.Listen(MouseButton.Right, ButtonState.Pressed, delegate { ostamassa = null; }, "Perutaan ostos");
732        //Mouse.ListenOn(huone, MouseButton.Right, ButtonState.Pressed, PoistaPaivitys, "Poistetaan asetettu päivitys", huone);
733
734        return huone;
735    }
736
737    private void PoistaPaivitys(Room huone)
738    {
739        if (huone.Upgrade != null)
740        {
741            kultuuri.Value += (int)(huone.Upgrade.Price * 0.5);
742            huone.Upgrade.Destroy();
743            huone.Upgrade = null;
744        }
745    }
746
747    void AsetaPaivitys(Room huone)
748    {
749        if (ostamassa != null && huone.Dug && kultuuri.Value >= ostamassa.Price && huone.Upgrade == null && huone != spawn)
750        {
751            // Kultuuripäivityksistä pitää olla reitti spawniin.
752            if (ostamassa is CultureUpgrade && FindPath(huone.Location, spawn.Location).Count == 0)
753                return;
754
755            kultuuri.Value -= ostamassa.Price;
756
757            // Lisätään päivitys huoneeseen.
758            huone.Upgrade = ostamassa;
759            Add(huone.Upgrade, -1);
760            huone.Upgrade.Position = huone.Position;
761            huone.Upgrade.Built(this);
762
763            ostamassa = null;
764            PaivitaHuoneenKultuuri(huone);
765        }
766    }
767
768    void PaivitaHuoneidenKultuurit()
769    {
770        RuutujenPaikat().Select(GetRoom).ToList().ForEach(PaivitaHuoneenKultuuri); // :D ;___;; MIKSI <- koska pystyn
771    }
772
773    void PaivitaHuoneenKultuuri(Room room)  //TODO: muokkauksia tuohon kultuurinarvonvaihtoon polun pituuden perusteella kunnes peli tuntuu oikeasti miellyttäviltä.
774    {
775        if (room != null && room.Upgrade != null && room.Upgrade is CultureUpgrade)
776        {
777            var upg = room.Upgrade as CultureUpgrade;
778
779            List<Point> polku = FindPath(room.Location, spawn.Location);
780            upg.Culture.Value = Math.Max(0, upg.Culture.MaxValue - (int)(upg.Culture.MaxValue * 0.10 * polku.Count));
781        }
782    }
783
784    GameObject CreateWall(Vector paikka, Direction suunta)
785    {
786        GameObject wall = new GameObject(RUUDUN_KOKO + 2, RUUDUN_KOKO + 2);
787        wall.Position = paikka;
788        wall.Image = seinaKuva;
789        wall.Angle = suunta.Angle;
790        Add(wall, 0);
791        return wall;
792    }
793
794    bool CanDig()
795    {
796        Room kohdeHuone = GetRoom(MuunnaJypelista(Mouse.PositionOnWorld));
797        if (kohdeHuone == null || KierrosKaynnissa % 2 == 0)
798        {
799            return false;
800        }
801
802        int dx = Math.Abs(kohdeHuone.Location.X - digStart.X);
803        int dy = Math.Abs(kohdeHuone.Location.Y - digStart.Y);
804        int hinta = (dx + dy) * HUONE_KAIVUU_HINTA;
805        kaivuuHintaLabel.Text = "" + hinta;
806        return ((dx > 0 && dy == 0) || (dy > 0 && dx == 0)) && kultuuri.Value >= hinta;
807    }
808
809    #region Reitinlöytö
810
811    List<Point> FindPath(Point alku, Point loppu)
812    {
813        if (GetRoom(alku) == null || GetRoom(loppu) == null)
814            return new List<Point>();
815
816        bool[,] walkable = new bool[huoneet.GetLength(0), huoneet.GetLength(1)];
817        foreach (var paikka in RuutujenPaikat())
818        {
819            walkable[paikka.X, paikka.Y] = huoneet[paikka.X, paikka.Y].Dug;
820        }
821        var finder = new AStar.PathFinder(new AStar.SearchParameters(loppu, alku, walkable), OviTarkistus);
822        return finder.FindPath();
823    }
824
825    bool OviTarkistus(Point a, Point b)
826    {
827        Room ra = GetRoom(a);
828        Room rb = GetRoom(b);
829        Direction suunta = (new Vector(b.X, b.Y) - new Vector(a.X, a.Y)).Angle.MainDirection;
830        if (ra != null && rb != null)
831        {
832            return ra.Walls[suunta].Image == reikaSeinaKuva && rb.Walls[Direction.Inverse(suunta)].Image == reikaSeinaKuva;
833        }
834        return false;
835    }
836
837    #endregion
838
839    #region Extra Juttuja
840
841    IEnumerable<Direction> Suunnat()
842    {
843        yield return Direction.Left;
844        yield return Direction.Right;
845        yield return Direction.Up;
846        yield return Direction.Down;
847    }
848
849    IEnumerable<Point> RuutujenPaikat()
850    {
851        return from y in Enumerable.Range(0, huoneet.GetLength(1))
852               from x in Enumerable.Range(0, huoneet.GetLength(0))
853               select new Point(x, y);
854    }
855
856    /// <summary>
857    /// Palauttaa ruutuja suoralta pätkältä dx ja dy verran alkaen pisteestä "alku".
858    /// dx tai dy pitää olla nolla.
859    /// </summary>
860    IEnumerable<Point> RuudutSuoralta(Point alku, int dx, int dy)
861    {
862        if (dx != 0)
863        {
864            for (int i = 0; i < Math.Abs(dx) + 1; i++)
865            {
866                yield return new Point(alku.X + i * Math.Sign(dx), alku.Y);
867            }
868            yield break;
869        }
870        if (dy != 0)
871        {
872            for (int i = 0; i < Math.Abs(dy) + 1; i++)
873            {
874                yield return new Point(alku.X, alku.Y + i * Math.Sign(dy));
875            }
876        }
877    }
878
879    Room GetRoom(Point paikka)
880    {
881        if (paikka.X >= 0 && paikka.X < huoneet.GetLength(0) && paikka.Y >= 0 && paikka.Y < huoneet.GetLength(1))
882        {
883            return huoneet[paikka.X, paikka.Y];
884        }
885        return null;
886    }
887
888    /// <summary>
889    /// Muuntaa Jypeli-koordinaatin peliruudukon koordinaatiksi.
890    /// </summary>
891    Point MuunnaJypelista(Vector paikka)
892    {
893        Vector siirrettyOrigo = (paikka - huoneSiirtyma) + RUUDUN_KOKO * (0.5 * new Vector(huoneet.GetLength(0), huoneet.GetLength(1)) + new Vector(0.5, 0.5));
894        Vector wtf = new Vector(siirrettyOrigo.X < 0 ? -1 : 0, siirrettyOrigo.Y < 0 ? -1 : 0);
895        Vector valmis = wtf + siirrettyOrigo / RUUDUN_KOKO;
896        return new Point((int)valmis.X, (int)valmis.Y);
897    }
898
899    public void LuoLentavaPartikkeli(Vector alkupaikka, Image kuva, double koko, int maara, bool veri = false)
900    {
901        // Feikki 3D partikkeli juttu.
902        // Heittää ilmaan GameObjekteja joiden alla on varjo.
903
904        // VAROITUS: SISÄLTÄÄ JÄRKYTTÄVÄÄ KOODIA
905
906        for (int i = 0; i < maara; i++)
907        {
908            GameObject partikkeli = new GameObject(koko, koko);
909            partikkeli.Image = kuva;
910            partikkeli.Position = alkupaikka + RandomGen.NextVector(0.0, RUUDUN_KOKO * 0.4);
911            Add(partikkeli, 3);
912
913            GameObject varjo = new GameObject(koko, koko / 2.0);
914            varjo.Position = partikkeli.Position;
915            varjo.Shape = Shape.Circle;
916            varjo.Color = Color.Lerp(Color.Black, Color.Transparent, 0.5);
917            Add(varjo, 2);
918
919            Vector paikka = partikkeli.Position;
920            Vector nopeus = RandomGen.NextVector(0.2, 3.0);
921            nopeus.Y *= 0.3;
922            double g = -0.2; // painovoima
923            double z = 0.0; // sijainti z-akselilla
924            double vz = RandomGen.NextDouble(3.5, 4.5); // nopeus z-akselilla
925            double angularVelocity = RandomGen.NextDouble(-1.0, 1.0) * 8;
926
927            var verenLuontiAjastin = veri ? new Timer() : null;
928
929            var ajastin = new Timer();
930            ajastin.Interval = 0.02;
931            ajastin.Timeout += delegate
932            {
933                vz += g;
934                z += vz;
935                paikka += nopeus;
936                partikkeli.Position = paikka + new Vector(0.0, 1.0) * z;
937                partikkeli.Angle += Angle.FromDegrees(angularVelocity);
938                varjo.Position = paikka;
939
940                if (z < 0.0)
941                {
942                    ajastin.Stop();
943                    partikkeli.Destroy();
944                    varjo.Destroy();
945                    if (verenLuontiAjastin != null)
946                        verenLuontiAjastin.Stop();
947                }
948            };
949            ajastin.Start();
950
951            if (verenLuontiAjastin != null)
952            {
953                verenLuontiAjastin.Interval = 0.1;
954                verenLuontiAjastin.Timeout += delegate
955                {
956                    GameObject veriPartikkeli = new GameObject(3, 3);
957                    veriPartikkeli.Color = Color.DarkRed;
958                    Add(veriPartikkeli, 2);
959
960                    Vector veriPaikka = paikka;
961                    double veriZ = z;
962                    double veriVz = 0.0;
963
964                    var veriPaivitysAjastin = new Timer();
965                    veriPaivitysAjastin.Interval = 0.02;
966                    veriPaivitysAjastin.Timeout += delegate
967                    {
968                        veriVz += g;
969                        veriZ += veriVz;
970                        veriPartikkeli.Position = veriPaikka + new Vector(0.0, 1.0) * veriZ;
971
972                        if (veriZ < 0.0)
973                        {
974                            veriPaivitysAjastin.Stop();
975                            veriPartikkeli.Destroy();
976                        }
977                    };
978                    veriPaivitysAjastin.Start();
979                };
980                verenLuontiAjastin.Start();
981            }
982        }
983    }
984
985    void LuoKiviPartikkelit(Vector alkupaikka)
986    {
987        LuoLentavaPartikkeli(alkupaikka, partikkeliKuva, 25, 6);
988    }
989
990    public void Splatter(Vector alkupaikka)
991    {
992        LuoLentavaPartikkeli(alkupaikka, taideVeri, 8, 10, true);
993    }
994
995    protected override void Update(Time time)
996    {
997        if (Digging)
998        {
999            Color vari = CanDig() ? Color.White : Color.Red;
1000            Vector alku = huoneet[digStart.X, digStart.Y].Position;
1001            Vector loppu = Mouse.PositionOnWorld;
1002            Vector suunta = loppu - alku;
1003            double pituus = suunta.Magnitude;
1004            if (pituus <= 2) pituus = 2;
1005
1006            digArrow.Color = vari;
1007            digArrow.Position = alku + suunta * 0.5;
1008            digArrow.Angle = suunta.Angle;
1009            digArrow.Width = pituus;
1010           
1011            digArrowHead.Color = vari;
1012            digArrowHead.Position = alku + suunta;
1013            digArrowHead.Angle = suunta.Angle - Angle.FromDegrees(90);
1014
1015            kaivuuHintaLabel.Position = Camera.WorldToScreen(alku + suunta * 0.5 + new Vector(0, 30));
1016        }
1017
1018        if (menu != null)
1019            menu.Update(time);
1020        base.Update(time);
1021    }
1022
1023    /*
1024    protected override void Paint(Canvas canvas)
1025    {
1026        canvas.BrushColor = Color.Purple;
1027
1028        var points = FindPath(new Point(6, 0), MuunnaJypelista(Mouse.PositionOnWorld));
1029        for (int i = 0; i < points.Count - 1; i++)
1030        {
1031            Vector v = huoneSiirtyma + new Vector(points[i].X - huoneet.GetLength(0) / 2, points[i].Y - huoneet.GetLength(1) / 2) * RUUDUN_KOKO;
1032            Vector v2 = huoneSiirtyma + new Vector(points[i + 1].X - huoneet.GetLength(0) / 2, points[i + 1].Y - huoneet.GetLength(1) / 2) * RUUDUN_KOKO;
1033            canvas.DrawLine(v, v2);
1034        }
1035
1036        base.Paint(canvas);
1037    }
1038    */
1039
1040    #endregion
1041}
Note: See TracBrowser for help on using the repository browser.