source: 2016/27/ohjaajat/VenienteFragore/VenienteFragore/VenienteFragore/VenienteFragore.cs @ 7806

Revision 7806, 15.6 KB checked in by tesatapa, 3 years ago (diff)

TimerAddonsiin? Until metodi, ja kiinniotto ja heittely

Line 
1using System;
2using System.Collections.Generic;
3using Jypeli;
4using Jypeli.Assets;
5using Jypeli.Controls;
6using Jypeli.Effects;
7using Jypeli.Widgets;
8
9class SimplePlatformCharacter : SimplePhysics.Object
10{
11    public bool IsGrounded { get; private set; }
12
13    public Direction FacingDirection { get; private set; }
14
15    public SimplePlatformCharacter(double width, double height) : base(width, height)
16    {
17        FacingDirection = Direction.Right;
18    }
19
20    public void Walk(double speed)
21    {
22        if (speed > 0) FacingDirection = Direction.Right;
23        if (speed < 0) FacingDirection = Direction.Left;
24        Velocity = new Vector(speed, Velocity.Y);
25    }
26
27    public override void Update(Time time)
28    {
29        base.Update(time);
30        IsGrounded = Game.Collisions(this, new Vector(0, -2), true).Count > 0;
31    }
32}
33
34class Player : SimplePlatformCharacter
35{
36    public bool IsCrouching { get; private set; }
37
38    public bool Crouch { get; set; }
39    public int PlayerNumber { get; set; }
40    public SimplePhysics.Object Carrying { get; set; }
41
42    private readonly double fullHeight;
43    private readonly double crouchHeight;
44
45    public List<Key> ControlKeys;
46
47    public Player(double width, double height) : base(width, height)
48    {
49        fullHeight = height;
50        crouchHeight = height / 2.0 - 1.0;
51    }
52
53    public void Reappear()
54    {
55        IsVisible = true;
56        IgnoresCollisionResponse = false;
57        IgnoresGravity = false;
58    }
59
60    public override void Destroy()
61    {
62        IsVisible = false;
63        IgnoresCollisionResponse = true;
64        IgnoresGravity = true;
65        Position = new Vector(Double.MinValue, Double.MinValue);
66    }
67
68    public override void Update(Time time)
69    {
70        if (!IsCrouching && Crouch)
71        {
72            var oldBottom = Bottom;
73            Height = crouchHeight;
74            Bottom = oldBottom;
75            IsCrouching = true;
76        }
77
78        if (IsCrouching && !Crouch)
79        {
80            var oldBottom = Bottom;
81            Height = fullHeight;
82            Bottom = oldBottom;
83            IsCrouching = false;
84
85            if (Game.Collisions(this, Vector.Zero, true).Count > 0)
86            {
87                Height = crouchHeight;
88                Bottom = oldBottom;
89                IsCrouching = true;
90            }
91        }
92
93        //Tämä tänne ehkä?
94        if (Carrying != null)
95        {
96            Carrying.X = this.X;
97            Carrying.Bottom = this.Top;
98        }
99
100        base.Update(time);
101    }
102}
103
104public static class TimerAddons
105{
106    public static void Until(Func<bool> predicate, Action action, double tickInterval = 0.1, Action onEnd = null)
107    {
108        Timer timer = new Timer();
109        timer.Interval = tickInterval;
110        timer.Timeout += delegate
111        {
112            if (predicate())
113            {
114                timer.Stop();
115                //Wut? this actually exists now in C#.. looks ugly as hell but is shorther than:
116                //if(onEnd != null) onEnd();
117                if (onEnd != null)
118                    onEnd.Invoke();
119            }
120            else
121            {
122                action();
123                //or action.Invoke();
124            }
125        };
126        timer.Start();
127
128    }
129}
130
131
132public class VenienteFragore : SimplePhysics.Game
133{
134    private delegate void ObjectMethod(Vector position, double width, double height, Dictionary<string, string> properties);
135    private Dictionary<string, ObjectMethod> objectMethods;
136
137    private List<Player> advenae = new List<Player>();
138
139    public VenienteFragore() : base(tileSize: 50)
140    {
141    }
142
143    public override void Begin()
144    {
145
146
147        objectMethods = new Dictionary<string, ObjectMethod>();
148        objectMethods.Add("ball", TestBall);
149        objectMethods.Add("player", CreatePlayer);
150        objectMethods.Add("moving", CreateMovingPlatform);
151
152        var tileMap = TiledTileMap.FromLevelAsset("thehub");
153        tileMap.SetTileMethod("Tiilet", TileMethod);
154        tileMap.SetObjectMethod("Oliot", CreateObject);
155        tileMap.SetTileMethod("Etuala", Foreground);
156        tileMap.Execute();
157
158        Gravity = new Vector(0, -800);
159
160        Camera.ZoomToLevel();
161
162
163        Level.Background.Color = Color.Beige;
164
165        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, "Lopeta peli");
166    }
167
168    private void CreateObject(Vector position, double width, double height, Angle angle, Shape shape, string name, Dictionary<string, string> properties)
169    {
170        objectMethods[name](position, width, height, properties);
171    }
172
173    void TestBall(Vector position, double width, double height, Dictionary<string, string> properties)
174    {
175        var testObject = new SimplePhysics.Object(TileSize * 0.99, TileSize * 0.99);
176        testObject.Position = position;
177        testObject.Color = Color.DarkGreen;
178        testObject.Shape = Shape.Circle;
179        testObject.RestitutionX = 0.5;
180        testObject.RestitutionY = 0.5;
181        testObject.CollisionIgnoreGroup = 1;
182        Add(testObject);
183    }
184
185    void CreatePlayer(Vector position, double width, double height, Dictionary<string, string> properties)
186    {
187        CreatePlayer1(position, width, height);
188        var p = CreatePlayer2(position, width, height);
189        p.Destroy();
190        SetGeneralKeys();
191    }
192
193    Player CreatePlayer1(Vector position, double width, double height)
194    {
195        if (advenae.Count > 0 && !advenae[0].IsVisible) { advenae[0].Reappear(); return advenae[0]; };
196
197        Player advenA = MakePlayer(position, width, height, 1, new List<Key> { Key.Up, Key.Down, Key.Left, Key.Right, Key.Enter });
198        advenA.Color = Color.HotPink;
199        advenae.Add(advenA);
200        return advenA;
201    }
202
203
204    Player CreatePlayer2(Vector position, double width, double height)
205    {
206        if (advenae.Count > 1 && !advenae[1].IsVisible) { advenae[1].Reappear(); return advenae[1]; };
207
208        Player advenA = MakePlayer(position, width, height, 2, new List<Key> { Key.W, Key.S, Key.A, Key.D, Key.E });
209        advenA.Color = Color.Harlequin;
210        advenae.Add(advenA);
211        return advenA;
212    }
213
214    private void SetMovementKeys(Player adven, List<Key> keys)
215    {
216        Keyboard.Listen(keys[3], ButtonState.Down, Walk, null, adven, 200.0);
217        Keyboard.Listen(keys[2], ButtonState.Down, Walk, null, adven, -200.0);
218        Keyboard.Listen(keys[0], ButtonState.Down, Jump, null, adven);
219        Keyboard.Listen(keys[1], ButtonState.Pressed, Crouch, null, adven, true);
220        Keyboard.Listen(keys[1], ButtonState.Released, Crouch, null, adven, false);
221        Keyboard.Listen(keys[4], ButtonState.Pressed, Interact, null, adven);
222        // Keyboard.Listen(keys[4], ButtonState.Pressed, SplitOrMorph, "Splits or morphs the player back to 1 player", adven);
223
224    }
225
226    private void Interact(Player adven)
227    {
228        //Jos kannetaan jotain, viskataan se
229        SimplePhysics.Object carryed = adven.Carrying; 
230        if( carryed != null) //Throw
231        {
232            adven.Carrying = null;
233            double dir = adven.FacingDirection == Direction.Left ? -1 : 1;
234            carryed.Velocity = new Vector(dir * 350, 350);
235            carryed.Position = carryed.Position + new Vector(dir * 10, 30);
236            //Pitäisiköhän oma aliohjelma tehdä
237            carryed.IgnoresGravity = false;
238            carryed.IgnoresCollisionResponse = false;
239        }
240
241        Vector pingPoint = adven.Position + (adven.FacingDirection == Direction.Left ? new Vector(-adven.Width, 0) : new Vector(adven.Width, 0));
242        List<GameObject> interactedObjects = GetObjectsAt(pingPoint);
243
244        GameObject sphere = new GameObject(1, 1);
245        sphere.Position = pingPoint;
246        sphere.Shape = Shape.Circle;
247        sphere.Color = new Color(100, 0, 100, 25);
248        Add(sphere, 1);
249
250        TimerAddons.Until(() => sphere.Width == 100.0, delegate { sphere.Width += 1; sphere.Height += 1; }, 0.01, sphere.Destroy);
251
252        foreach (GameObject item in interactedObjects)
253        {
254            SimplePhysics.Object obj = item as SimplePhysics.Object;
255            if (obj == null)
256                continue;
257            InteractWith(adven, obj);
258        }
259    }
260
261
262    private void InteractWith(Player adven, SimplePhysics.Object interactedWith)
263    {
264        if(adven.Carrying == null)
265        {
266            adven.Carrying = interactedWith;
267            interactedWith.IgnoresGravity = true;
268            interactedWith.IgnoresCollisionResponse = true;
269            //Lentävän palikan nostaminen
270        }
271    }
272
273
274
275
276    /*
277     private void SetMovementKeys(Player adven, Key up, Key down, Key left, Key right, Key morph)
278     {
279         Keyboard.Listen(right, ButtonState.Down, Walk, null, adven, 200.0);
280         Keyboard.Listen(left, ButtonState.Down, Walk, null, adven, -200.0);
281         Keyboard.Listen(up, ButtonState.Down, Jump, null, adven);
282         Keyboard.Listen(down, ButtonState.Pressed, Crouch, null, adven, true);
283         Keyboard.Listen(down, ButtonState.Released, Crouch, null, adven, false);
284
285         Keyboard.Listen(morph, ButtonState.Pressed, SplitOrMorph, "Splits or morphs the player back to 1 player");
286
287     }
288     */
289
290    private void SetGeneralKeys()
291    {
292        Keyboard.Listen(Key.R, ButtonState.Pressed, () => { ClearAll(); advenae = new List<Player>(); Begin(); }, "Lopeta peli");
293        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, "Lopeta peli");
294
295        //Keyboard.Listen(keys[4], ButtonState.Pressed, SplitOrMorph, "Splits or morphs the player back to 1 player", adven);
296        Keyboard.Listen(Key.X, ButtonState.Pressed, SplitOrMorph, "Splits or morphs the player", 2);
297        Keyboard.Listen(Key.RightShift, ButtonState.Pressed, SplitOrMorph, "Splits or morphs the player", 1);
298        Keyboard.Listen(Key.LeftShift, ButtonState.Pressed, () => { advenae[0].Reappear(); advenae[0].X = Level.Left - advenae[0].Width; }, "");
299    }
300
301
302    private Player MakePlayer(Vector position, double width, double height, int playerNum, List<Key> keys)
303    {
304        Player adven = new Player(TileSize * 0.99, TileSize * 1.98);
305        adven.Position = position;
306        adven.Friction = 0.2;
307        adven.Tag = "player";
308        adven.Crushed += adven.Destroy;
309        //adven.Destroyed += delegate { advenae.Remove(adven); };
310        adven.CollisionIgnoreGroup = playerNum;
311        adven.PlayerNumber = playerNum;
312        //adven.AddCollisionHandler("player", HandleMorphing);
313        adven.ControlKeys = keys;
314        Add(adven);
315
316        adven.AddCollisionHandler("death", (a, b) => adven.Destroy());
317
318        SetMovementKeys(adven, keys);
319
320        return adven;
321    }
322
323    /// <summary>
324    /// Sotku
325    /// </summary>
326    /// <param name="playerNro">Sen pelaajan numero, joka haluaa toimia</param>
327    private void SplitOrMorph(int playerNro)
328    {
329        //if (advenae.FindAll(o => o.IsVisible == true).Count == 1)
330        if(!advenae[playerNro-1].IsVisible && advenae[1 - playerNro + 1].IsVisible)
331        {
332            Split(advenae[1 - playerNro + 1]);
333        }
334        else
335        {
336            Morph(advenae[1 - playerNro + 1]);
337        }
338    }
339
340    private void Morph(Player adven)
341    {
342        if (advenae.FindAll(o => o.IsVisible == true).Count != 2) return;
343
344        if (Vector.Distance(advenae[0].Position, advenae[1].Position) < adven.Width * 1.5)
345        {
346            Player destroyable = advenae.Find(o => o.PlayerNumber != adven.PlayerNumber);
347
348            /*destroyable.ControlKeys.ForEach(delegate (Key key)
349            {
350                Keyboard.Disable(key);
351            });*/
352
353            destroyable.Destroy();
354        }
355
356        //TODO: Eeppinen hypäytys takaisin? Samalla voisi ajastimella tarkastaa jatkuvasti, ovatko pelaajat tarpeeksi lähellä toisiaan.
357        /*
358        Vector center = new Vector();
359
360        for (int i = 0; i < advenae.Count; i++)
361        {
362            center = (advenae[i].Position - center) * 0.5;
363        }
364        foreach (Player item in advenae)
365        {
366            item.Velocity = (center - item.Position) * 3.0;
367        }
368        morphing = true;
369        Timer.SingleShot(2.0, delegate { morphing = false; });
370        */
371    }
372
373    void Split(Player adven)
374    {
375        if (advenae.FindAll(o => o.IsVisible == true).Count == 2) return;
376
377        Player advenNew = new Player(adven.Width, adven.Height);
378        switch (adven.PlayerNumber)
379        {
380            case 1:
381                advenNew = CreatePlayer2(adven.Position + new Vector(adven.Width, 0), adven.Width, adven.Height);
382                break;
383            case 2:
384                advenNew = CreatePlayer1(adven.Position + new Vector(adven.Width, 0), adven.Width, adven.Height);
385                break;
386            default:
387                break;
388        }
389
390        advenNew.Position = adven.Position + new Vector(adven.Width, 0);
391
392        if (Collisions(advenNew, Vector.Zero, true).Count > 0)
393        {
394            advenNew.Destroy();
395            return;
396        }
397
398        advenNew.ControlKeys.ForEach(delegate (Key key)
399        {
400            Keyboard.Enable(key);
401        });
402    }
403
404    void Walk(Player pelaaja, double nopeus)
405    {
406        pelaaja.Walk(nopeus);
407    }
408
409    private void Jump(SimplePlatformCharacter player)
410    {
411        if (player.IsGrounded)
412            player.Velocity = new Vector(player.Velocity.X, 500);
413    }
414
415    private void Crouch(Player player, bool crouch)
416    {
417        player.Crouch = crouch;
418    }
419
420    private void CreateMovingPlatform(Vector position, double width, double height, Dictionary<string, string> properties)
421    {
422        var dirX = double.Parse(properties["directionx"]);
423        var dirY = double.Parse(properties["directiony"]);
424        var distance = double.Parse(properties["distance"]);
425        var platform = new MovingPlatform(position, new Vector(dirX, dirY), distance, width, height);
426        Add(platform);
427    }
428
429    private void Foreground(int x, int y, Image image, string layerName, Dictionary<string, string> properties)
430    {
431        var tile = new SimplePhysics.Object(TileSize, TileSize) { IsStatic = true };
432        tile.Image = image;
433        tile.IgnoresCollisionResponse = true;
434        Add(tile, 3);
435        SetTile(x, y, tile);
436    }
437
438    private void TileMethod(int x, int y, Image image, string layerName, Dictionary<string, string> properties)
439    {
440        var tile = new SimplePhysics.Object(TileSize, TileSize) { IsStatic = true };
441        tile.Image = image;
442        Add(tile);
443        SetTile(x, y, tile);
444
445        if (properties.ContainsKey("type"))
446        {
447            var features = properties["type"].Split(',');
448            foreach (var feature in features)
449            {
450                ApplyFeature(tile, feature);
451            }
452        }
453    }
454
455    private void ApplyFeature(SimplePhysics.Object tile, string feature)
456    {
457        switch (feature)
458        {
459            case "ice":
460                tile.Friction = 0.0;
461                break;
462
463            case "death":
464                tile.Tag = "death";
465                break;
466
467            case "oneway":
468                tile.OneWayPlatform = true;
469                break;
470
471            case "break":
472                tile.AddCollisionHandler("player", (t, player) =>
473                {
474                    if (player.Top <= tile.Bottom)
475                    {
476                        tile.Destroy();
477                    }
478                });
479                break;
480            default:
481                throw new Exception("Unknown tile feature: " + feature);
482        }
483    }
484}
Note: See TracBrowser for help on using the repository browser.