public void Update() { bool crushedLeft = false, crushedRight = false, crushedTop = false, crushedBottom = false; // Boolean values to check if the body is "crushed" IsCollidingOnBottom = false; // Boolean value to check if the body is on the ground List invokations = new List(); // List of "detection events" invokations PositionPrevious = Position; // Sets the previous position to the current position if (IsAffectedByGravity) Velocity += World.Gravity; // Adds gravity to velocity Position += Velocity; // Adds velocity to position List bodiesToCheck = World.Grid.GetBodiesIn(new Rectangle(Left, Top, Width, Height)); // Gets nearby bodies from spatial hash if (Velocity.Y < 0) bodiesToCheck.Sort((b, a) => a.Position.Y.CompareTo(b.Position.Y)); // Sorts bodies by Y axis to avoid wall-jumping bugs else bodiesToCheck.Sort((a, b) => a.Position.Y.CompareTo(b.Position.Y)); for (int i = 0; i < bodiesToCheck.Count; i++) // Detection loop { SSSPBody body = bodiesToCheck[i]; if (IgnoresDetectionWith(body)) continue; // If the body has to be ignored, continue if (!SSSPUtils.IsOverlapping(this, body, new SSSPVector2(0, 0))) continue; // If there isn't any overlap, continue int encrX = 0, encrY = 0; // Penetration values (X and Y) if (Bottom < body.Bottom && Bottom >= body.Top) encrY = body.Top - Bottom; // Calculates Y penetration else if (Top > body.Top && Top <= body.Bottom) encrY = body.Bottom - Top; if (Left < body.Left && Right >= body.Left) encrX = body.Left - Right; // Calculates X penetration else if (Right > body.Right && Left <= body.Right) encrX = body.Right - Left; invokations.Add(new object[] { body, encrX, encrY }); // Adds "detection event" invokation } for (int i = 0; i < bodiesToCheck.Count; i++) // Resolution loop { SSSPBody body = bodiesToCheck[i]; if (IgnoresDetectionWith(body)) continue; // If the body has to be ignored, continue if (!SSSPUtils.IsOverlapping(this, body, new SSSPVector2(0, 0))) continue; // If there isn't any overlap, continue int encrX = 0, encrY = 0, numPxOverlapX, numPxOverlapY; // Penetration values and overlap values if (Bottom < body.Bottom && Bottom >= body.Top) encrY = body.Top - Bottom; // Calculates Y penetration else if (Top > body.Top && Top <= body.Bottom) encrY = body.Bottom - Top; if (Left < body.Left && Right >= body.Left) encrX = body.Left - Right; // Calculates X penetration else if (Right > body.Right && Left <= body.Right) encrX = body.Right - Left; if (Left < body.Left) numPxOverlapX = Right - body.Left; // Calculates X overlap else numPxOverlapX = body.Right - Left; if (Top < body.Top) numPxOverlapY = Bottom - body.Top; // Calculates Y overlap else numPxOverlapY = body.Bottom - Top; if (IgnoresResolutionWith(body, new SSSPVector2(encrX, encrY))) continue; // If resolution has to be ignored, continue if (Left >= body.Left && Top >= body.Top) crushedLeft = true; // Checks for crushing if (Right <= body.Right && Top >= body.Top) crushedRight = true; if (Left >= body.Left && Bottom <= body.Bottom) crushedTop = true; if (Right <= body.Right && Bottom <= body.Bottom) crushedBottom = true; if (numPxOverlapX > numPxOverlapY) { Position += new SSSPVector2(0, encrY); // Resolves penetration body.Velocity = new SSSPVector2(body.Velocity.X, Velocity.Y); // Transfers velocity } else { Position += new SSSPVector2(encrX, 0); body.Velocity = new SSSPVector2(Velocity.X, body.Velocity.Y); } if (SSSPUtils.IsOverlapping(this, body, new SSSPVector2(PositionPrevious.X - Position.X, Math.Abs(Velocity.Y) * Math.Sign(World.Gravity.Y)))) IsCollidingOnBottom = true; // Checks if the body is on the ground SSSPVector2 checkPosition = PositionPrevious - (body.PositionPrevious - body.Position); // Calculates difference vector for moving platforms if (encrX > 0 && Velocity.X < 0 && Position.X == checkPosition.X) Velocity = new SSSPVector2(0, Velocity.Y); // Sets velocity to 0 if the body is on a moving platform if (encrX < 0 && Velocity.X > 0 && Position.X == checkPosition.X) Velocity = new SSSPVector2(0, Velocity.Y); if (encrY < 0 && Velocity.Y > 0 && Position.Y == checkPosition.Y) Velocity = new SSSPVector2(Velocity.X, 0); if (encrY > 0 && Velocity.Y < 0 && Position.Y == checkPosition.Y) Velocity = new SSSPVector2(Velocity.X, 0); } if (Position.X == PositionPrevious.X) Velocity = new SSSPVector2(0, Velocity.Y); // If the body hasn't moved, set velocity to 0 if (Position.Y == PositionPrevious.Y) Velocity = new SSSPVector2(Velocity.X, 0); foreach (object[] objects in invokations) { InvokeOnOverlap((SSSPBody)objects[0], new SSSPVector2((int)objects[1], (int)objects[2])); // Calls overlap events in the bodies SSSPBody b = (SSSPBody)objects[0]; b.InvokeOnOverlap(this, new SSSPVector2((int)objects[1] * -1, (int)objects[2] * -1)); } if (crushedLeft && crushedRight && crushedTop && crushedBottom) InvokeOnCrush(this, new SSSPVector2(0, 0)); // Calls crush event in the body }