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

Revision 6004, 14.1 KB checked in by sieerinn, 6 years ago (diff)

Partikkeleiden parametreja säädetty.

Line 
1using System;
2using System.Linq;
3using System.Collections.Generic;
4using Jypeli;
5using Jypeli.Assets;
6using Jypeli.Controls;
7using Jypeli.Effects;
8using Jypeli.Widgets;
9using Point = Microsoft.Xna.Framework.Point;
10
11class Room : GameObject
12{
13    // Sijainti pelin ruudukossa.
14    public Point Location { get; set; }
15
16    // Päällä näkyvä "katto" kun huone ei ole vielä kaivettu.
17    public GameObject Roof { get; set; }
18
19    // Neljä seinää, jotka on GameObjekteja.
20    public Dictionary<Direction, GameObject> Walls { get; set; }
21
22    public String Type { get; set; }
23
24    public int Damage { get; set; }
25
26    public int Culture { get; set; }
27
28    private bool dug; // Onko huone kaivettu?
29    public bool Dug
30    {
31        get { return dug; }
32        set
33        {
34            dug = value;
35            Roof.IsVisible = !Dug;
36        }
37    }
38
39    public Room(Point paikka)
40        : base(Dungeon.RUUDUN_KOKO, Dungeon.RUUDUN_KOKO)
41    {
42        Walls = new Dictionary<Direction, GameObject>();
43        Location = paikka;
44    }
45
46    public int Price { get; set; }
47
48}
49
50public class Dungeon : PhysicsGame
51{
52    public const int RUUDUN_KOKO = 64;
53
54    #region Kuvat
55    Image lattiaKuva = LoadImage("floor");
56    Image seinaKuva = LoadImage("wall");
57    Image reikaSeinaKuva = LoadImage("wallhole");
58    Image kiviKuva = LoadImage("rock");
59    static Image kulttuuriKuva1 = LoadImage("es");
60    static Image kulttuuriKuva2 = LoadImage("nyan");
61    static Image kulttuuriKuva3 = LoadImage("spurdo");
62    Image[] huoneKuvat = new Image[] { kulttuuriKuva1, kulttuuriKuva2, kulttuuriKuva3 };
63    Image[] vihuKuvat = LoadImages((from i in Enumerable.Range(1, 10) select String.Format("v{0:0000}", i)).ToArray());
64    Image partikkeli = LoadImage("partikkeli");
65    #endregion
66
67    int[] hinnat = new int[] { 100, 200, 300 };
68    private int barbaariMaara = 3;
69
70    Room[,] huoneet;
71    Room spawn;
72    Timer barbaariAjastin = new Timer();
73    Room ostettu;
74    Point digStart; // Huoneen sijainti, josta kaivuu aloitetaan.
75    bool digging = false;
76
77    GameObject digArrow;
78    GameObject digArrowHead;
79
80    IntMeter kulttuuri = new IntMeter(300, 0, 2000);
81
82    int vaakaHuoneet = 12;
83    int pystyHuoneet = 8;
84
85    public override void Begin()
86    {
87        ClearAll();
88        Kontrollit();
89        UlkoAsuRoskaa();
90        Kauppa();
91        Nuoli();
92
93        // Luodaan huoneet ruutuihin.
94        huoneet = new Room[vaakaHuoneet, pystyHuoneet];
95        foreach (var paikka in RuutujenPaikat())
96        {
97            var huone = CreateRoom(paikka);
98            Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Pressed, () => RoomPressed(huone), null);
99            Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Released, () => RoomReleased(huone), null);
100            huoneet[paikka.X, paikka.Y] = huone;
101        }
102
103        LuoSpawn();
104
105        barbaariAjastin.Timeout += delegate { LuoBarbaareja(); };
106        barbaariAjastin.Interval = 3;
107    }
108
109    void Nuoli()
110    {
111        digArrow = new GameObject(5, 5);
112        digArrowHead = new GameObject(15, 15);
113        digArrowHead.Shape = Shape.Triangle;
114        digArrowHead.IsVisible = digArrow.IsVisible = false;
115        Add(digArrow, 3);
116        Add(digArrowHead, 3);
117    }
118
119    void UlkoAsuRoskaa()
120    {
121        Level.Background.Color = Color.Black;
122
123        Label rahat = new Label();
124        rahat.BindTo(kulttuuri);
125        rahat.Position = new Vector(Level.Right + Level.Width * 0.2, Level.Bottom + Level.Height * 0.1);
126        rahat.TextColor = Color.White;
127        rahat.IntFormatString = "Käytettävää kulttuuria: {0:D3}";
128        Add(rahat);
129    }
130
131    void Kauppa()
132    {
133        for (int i = 0; i < huoneKuvat.Length; i++)
134        {
135            Point lokaatio = new Point(0, 0);
136
137            Room kuva = new Room(lokaatio);
138            kuva.Position = new Vector((Level.Right + Level.Width * 0.05), (Level.Top - Level.Height * 0.25 - (i * RUUDUN_KOKO)));
139            kuva.Image = huoneKuvat[i];
140            kuva.Price = hinnat[i];
141            Add(kuva);
142
143            Mouse.ListenOn(kuva, MouseButton.Left, ButtonState.Pressed, delegate(Room a) { ostettu = a; }, "Asetetaan ostettu huone paikoilleen", kuva);
144
145            Label teksti = new Label();
146            teksti.Position = kuva.Position + new Vector((RUUDUN_KOKO * 1.2), 0);
147            teksti.TextColor = Color.White;
148            teksti.Text = hinnat[i].ToString();
149            Add(teksti);
150        }
151    }
152
153    void LuoBarbaareja()
154    {
155        PhysicsObject barbaari = new PhysicsObject(RUUDUN_KOKO * 0.4, RUUDUN_KOKO * 0.4);
156        barbaari.Color = Color.Red;
157        //barbaari.Position = RandomGen.NextVector(Level.Right, Level.Bottom, Level.Left, Level.Top);
158        barbaari.Position = spawn.Position;
159        barbaari.Animation = new Animation(vihuKuvat);
160        barbaari.Animation.FPS = 10;
161        barbaari.Animation.Start();
162        Add(barbaari);
163    }
164
165    void Kontrollit()
166    {
167        IsMouseVisible = true;
168        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, "Lopeta peli");
169        Keyboard.Listen(Key.F1, ButtonState.Pressed, Begin, null);
170
171        Keyboard.Listen(Key.Space, ButtonState.Pressed, SeuraavaAalto, "Anna kivan barbaariaallon tulla");
172    }
173
174    void SeuraavaAalto()
175    {
176        barbaariMaara += 2;
177        barbaariAjastin.Start(barbaariMaara);
178    }
179
180    void LuoSpawn()
181    {
182        spawn = huoneet[(int)(huoneet.GetLength(0) * 0.5), 0];
183        spawn.Dug = true;
184
185        Direction oviSuunta = ((spawn.Position - new Vector(0, RUUDUN_KOKO * 0.5)).Angle.MainDirection);
186        spawn.Walls[oviSuunta].Image = reikaSeinaKuva;
187
188        Light valo = new Light();
189        valo.Position = spawn.Position;
190        valo.Intensity = 1;
191        valo.Distance = 40;
192        Add(valo);
193       
194    }
195
196    void LuoKiviPartikkelit(Vector alkupaikka)
197    {
198        /*  Ei toimi koska jää huoneiden kattojen alle.
199        ExplosionSystem rajahdys = new ExplosionSystem(LoadImage("partikkeli"), 200);
200        Add(rajahdys);
201        rajahdys.AddEffect(paikka.X, paikka.Y, 20);
202         */
203
204        // Feikki 3D partikkeli juttu.
205        // Heittää ilmaan GameObjekteja joiden alla on varjo.
206        for (int i = 0; i < 6; i++)
207        {
208            GameObject p = new GameObject(25, 25);
209            p.Image = partikkeli;
210            p.Position = alkupaikka + RandomGen.NextVector(0.0, RUUDUN_KOKO * 0.4);
211            Add(p, 3);
212
213            GameObject varjo = new GameObject(20, 10);
214            varjo.Position = p.Position;
215            varjo.Shape = Shape.Circle;
216            varjo.Color = Color.Lerp(Color.Black, Color.Transparent, 0.5);
217            Add(varjo, 2);
218
219            Vector paikka = p.Position;
220            Vector nopeus = RandomGen.NextVector(0.2, 3.0);
221            nopeus.Y *= 0.3;
222            double g = -0.2; // painovoima
223            double z = 0.0; // sijainti z-akselilla
224            double vz = RandomGen.NextDouble(3.5, 4.5); // nopeus z-akselilla
225            double angularVelocity = RandomGen.NextDouble(-1.0, 1.0) * 8;
226
227            Timer ajastin = new Timer();
228            ajastin.Interval = 0.02;
229            ajastin.Timeout += delegate
230            {
231                vz += g;
232                z += vz;
233                paikka += nopeus;
234                p.Position = paikka + new Vector(0.0, 1.0) * z;
235                p.Angle += Angle.FromDegrees(angularVelocity);
236                varjo.Position = paikka;
237
238                if (z < 0.0)
239                {
240                    ajastin.Stop();
241                    p.Destroy();
242                    varjo.Destroy();
243                }
244            };
245            ajastin.Start();
246        }
247    }
248
249    void RoomPressed(Room huone)
250    {
251        digStart = huone.Location;
252        digging = true;
253        digArrowHead.IsVisible = digArrow.IsVisible = true;
254    }
255
256    void RoomReleased(Room kohdeHuone)
257    {
258        digging = false;
259        digArrowHead.IsVisible = digArrow.IsVisible = false;
260        if (CanDig()) 
261        {
262            var alkuHuone = huoneet[digStart.X, digStart.Y];
263
264            // Hienot partikkeliefektit.
265            if (!kohdeHuone.Dug)
266                LuoKiviPartikkelit(kohdeHuone.Position);
267            if (!alkuHuone.Dug)
268                LuoKiviPartikkelit(alkuHuone.Position);
269
270            // Merkataan huoneet kaivetuksi.
271            kohdeHuone.Dug = alkuHuone.Dug = true;
272
273            // Reiät seinään.
274            Direction oviSuunta = (kohdeHuone.Position - alkuHuone.Position).Angle.MainDirection;
275            Direction toinenOviSuunta = Direction.Inverse(oviSuunta);
276            alkuHuone.Walls[oviSuunta].Image = reikaSeinaKuva;
277            kohdeHuone.Walls[toinenOviSuunta].Image = reikaSeinaKuva;
278        }
279    }
280
281    Room CreateRoom(Point paikka)
282    {
283        Room huone = new Room(paikka);
284        huone.Image = lattiaKuva;
285        huone.Position = new Vector(paikka.X - huoneet.GetLength(0) / 2, paikka.Y - huoneet.GetLength(1) / 2) * RUUDUN_KOKO;
286        foreach (var suunta in Suunnat())
287            huone.Walls[suunta] = CreateWall(huone.Position, suunta);
288        Add(huone, -1);
289        huone.Roof = new GameObject(RUUDUN_KOKO, RUUDUN_KOKO);
290        huone.Roof.Image = kiviKuva;
291        huone.Roof.Position = huone.Position;
292        Add(huone.Roof, 1);
293
294        Mouse.ListenOn(huone, MouseButton.Left, ButtonState.Pressed, AsetaHuone, "Asetetaan ostettu huone paikoilleen", huone);
295
296        return huone;
297    }
298
299    void AsetaHuone(Room huone)
300    {
301        if(ostettu != null && huone.Dug && (kulttuuri.Value > huone.Price))
302        {
303            huone.Damage = ostettu.Damage;
304            huone.Culture = ostettu.Culture;
305            huone.Image = ostettu.Image;
306            kulttuuri.Value -= ostettu.Price;
307            ostettu = null;
308        }
309    }
310
311    GameObject CreateWall(Vector paikka, Direction suunta)
312    {
313        GameObject wall = new GameObject(RUUDUN_KOKO + 2, RUUDUN_KOKO + 2);
314        wall.Position = paikka;
315        wall.Image = seinaKuva;
316        wall.Angle = suunta.Angle;
317        Add(wall, 0);
318        return wall;
319    }
320
321    bool CanDig()
322    {
323        Room kohdeHuone = GetRoom(MuunnaJypelista(Mouse.PositionOnWorld));
324        if (kohdeHuone == null)
325        {
326            return false;
327        }
328        int dx = Math.Abs(kohdeHuone.Location.X - digStart.X);
329        int dy = Math.Abs(kohdeHuone.Location.Y - digStart.Y);
330        return dx + dy == 1;
331    }
332
333    protected override void Update(Time time)
334    {
335        if (digging)
336        {
337            Color vari = CanDig() ? Color.White : Color.Red;
338            Vector alku = huoneet[digStart.X, digStart.Y].Position;
339            Vector loppu = Mouse.PositionOnWorld;
340            Vector suunta = loppu - alku;
341            double pituus = suunta.Magnitude;
342            if (pituus <= 2) pituus = 2;
343
344            digArrow.Color = vari;
345            digArrow.Position = alku + suunta * 0.5;
346            digArrow.Angle = suunta.Angle;
347            digArrow.Width = pituus;
348
349            digArrowHead.Color = vari;
350            digArrowHead.Position = alku + suunta;
351            digArrowHead.Angle = suunta.Angle - Angle.FromDegrees(90);
352        }
353
354        base.Update(time);
355    }
356
357    protected override void Paint(Canvas canvas)
358    {
359        canvas.BrushColor = Color.Purple;
360
361        var points = FindPath(new Point(6, 0), MuunnaJypelista(Mouse.PositionOnWorld));
362        for (int i = 0; i < points.Count - 1; i++)
363        {
364            Vector v = new Vector(points[i].X - huoneet.GetLength(0) / 2, points[i].Y - huoneet.GetLength(1) / 2) * RUUDUN_KOKO;
365            Vector v2 = new Vector(points[i+1].X - huoneet.GetLength(0) / 2, points[i+1].Y - huoneet.GetLength(1) / 2) * RUUDUN_KOKO;
366            canvas.DrawLine(v, v2);
367        }
368
369        base.Paint(canvas);
370    }
371
372    #region Reitinlöytö
373
374    List<Point> FindPath(Point alku, Point loppu)
375    {
376        if (GetRoom(alku) == null || GetRoom(loppu) == null)
377            return new List<Point>();
378
379        bool[,] walkable = new bool[huoneet.GetLength(0), huoneet.GetLength(1)];
380        foreach (var paikka in RuutujenPaikat())
381        {
382            walkable[paikka.X, paikka.Y] = huoneet[paikka.X, paikka.Y].Dug;
383        }
384        var finder = new AStar.PathFinder(new AStar.SearchParameters(alku, loppu, walkable), OviTarkistus);
385        return finder.FindPath();
386    }
387
388    bool OviTarkistus(Point a, Point b)
389    {
390        Room ra = GetRoom(a);
391        Room rb = GetRoom(b);
392        Direction suunta = (new Vector(b.X, b.Y) - new Vector(a.X, a.Y)).Angle.MainDirection;
393        if (ra != null && rb != null)
394        {
395            return ra.Walls[suunta].Image == reikaSeinaKuva && rb.Walls[Direction.Inverse(suunta)].Image == reikaSeinaKuva;
396        }
397        return false;
398    }
399
400    #endregion
401
402    #region Extra Juttuja
403
404    IEnumerable<Direction> Suunnat()
405    {
406        yield return Direction.Left;
407        yield return Direction.Right;
408        yield return Direction.Up;
409        yield return Direction.Down;
410    }
411
412    IEnumerable<Point> RuutujenPaikat()
413    {
414        return from y in Enumerable.Range(0, huoneet.GetLength(1))
415               from x in Enumerable.Range(0, huoneet.GetLength(0))
416               select new Point(x, y);
417    }
418
419    Room GetRoom(Point paikka)
420    {
421        if (paikka.X >= 0 && paikka.X < huoneet.GetLength(0) && paikka.Y >= 0 && paikka.Y < huoneet.GetLength(1))
422        {
423            return huoneet[paikka.X, paikka.Y];
424        }
425        return null;
426    }
427
428    /// <summary>
429    /// Muuntaa Jypeli-koordinaatin peliruudukon koordinaatiksi.
430    /// </summary>
431    Point MuunnaJypelista(Vector paikka)
432    {
433        Vector siirrettyOrigo = paikka + RUUDUN_KOKO * (0.5 * new Vector(huoneet.GetLength(0), huoneet.GetLength(1)) + new Vector(0.5, 0.5));
434        Vector wtf = new Vector(siirrettyOrigo.X < 0 ? -1 : 0, siirrettyOrigo.Y < 0 ? -1 : 0);
435        Vector valmis = wtf + siirrettyOrigo / RUUDUN_KOKO;
436        return new Point((int)valmis.X, (int)valmis.Y);
437    }
438
439    #endregion
440}
Note: See TracBrowser for help on using the repository browser.