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

Revision 7816, 17.3 KB checked in by empaheik, 3 years ago (diff)

Kamera yrittää seurata kahta pelaajaa

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