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

Revision 6104, 33.7 KB checked in by sieerinn, 6 years ago (diff)

Kultuurille animaatiota ja uudet kuvat.

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