| private void HandleCollisions() |
| { |
| // Get the player's bounding rectangle and find neighboring tiles. |
| Rectangle bounds = BoundingRectangle; |
| int leftTile = (int)Math.Floor((float)bounds.Left / Tile.Width); |
| int rightTile = (int)Math.Ceiling(((float)bounds.Right / Tile.Width)) - 1; |
| int topTile = (int)Math.Floor((float)bounds.Top / Tile.Height); |
| int bottomTile = (int)Math.Ceiling(((float)bounds.Bottom / Tile.Height)) - 1; |
| |
| float dist = |
| (float)Math.Sqrt |
| (Math.Pow |
| (MathHelper.Clamp |
| (bounds.Center.X - bounds.Left, 0, Tile.Width), 2) + |
| Math.Pow |
| (MathHelper.Clamp |
| (bounds.Bottom - bounds.Bottom, 0, Tile.Height), 2)); |
| |
| float slopeTopLeft = |
| (bounds.Bottom - |
| ((bounds.Center.X - bounds.Left) * |
| (float)Math.Sin |
| (Math.Atan2 |
| (bounds.Height, |
| (bounds.Center.X - bounds.Left))))); |
| |
| float slopeTopRight = |
| (bounds.Bottom - |
| ((bounds.Center.X - bounds.Right) * |
| (float)Math.Sin |
| (Math.Atan2 |
| (bounds.Height, |
| (bounds.Center.X - bounds.Right))))); |
| |
| |
| // Reset flag to search for ground collision. |
| isOnGround = false; |
| |
| // For each potentially colliding tile, |
| for (int y = topTile; y <= bottomTile; ++y) |
| { |
| for (int x = leftTile; x <= rightTile; ++x) |
| { |
| // If this tile is collidable, |
| TileCollision collision = Level.GetCollision(x, y); |
| if (collision != TileCollision.Passable) |
| { |
| // Determine collision depth (with direction) and magnitude. |
| Rectangle tileBounds = Level.GetBounds(x, y); |
| Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds); |
| if (depth != Vector2.Zero) |
| { |
| float absDepthX = Math.Abs(depth.X); |
| float absDepthY = Math.Abs(depth.Y); |
| |
| // Resolve the collision along the shallow axis. |
| if (absDepthY < absDepthX || collision == TileCollision.Platform) |
| { |
| //if (!isOnSlope) |
| //{ |
| // If we crossed the top of a tile, we are on the ground. |
| if (previousBottom <= tileBounds.Top) |
| isOnGround = true; |
| //} |
| |
| // Ignore platforms, unless we are on the ground. |
| if (collision == TileCollision.Impassable || IsOnGround) |
| { |
| //if (!isOnSlope) |
| //{ |
| // Resolve the collision along the Y axis. |
| Position = new Vector2(Position.X, Position.Y + depth.Y); |
| |
| // Perform further collisions with the new bounds. |
| bounds = BoundingRectangle; |
| //} |
| } |
| } |
| else if (collision == TileCollision.Impassable) // Ignore platforms. |
| { |
| if (!isOnSlope) |
| { |
| // Resolve the collision along the X axis. |
| Position = new Vector2(Position.X + depth.X, Position.Y); |
| |
| // Perform further collisions with the new bounds. |
| bounds = BoundingRectangle; |
| } |
| } |
| } |
| /*if (collision == TileCollision.RampUp) |
| { |
| Rectangle triangle = BoundingRectangle; |
| //int leftTri = (int)Math.Floor((float)bounds.Left / Tile.Width); |
| //int rightTri = (int)Math.Ceiling(((float)bounds.Right / Tile.Width)) - 1; |
| //int topTri = (int)Math.Floor((float)bounds.Top / Tile.Height); |
| //int bottomTri = (int)Math.Ceiling(((float)triangle.Bottom / Tile.Height)) - 1; |
| }*/ |
| } |
| if (collision == TileCollision.SlopeLeft) |
| { |
| if (isOnSlope) |
| { |
| if (isJumping == false) |
| { |
| // Resolve the collision along the Y axis. |
| Position = new Vector2 |
| (Position.X, slopeTopLeft); |
| Position = new Vector2 |
| ((float)Math.Round(Position.X), |
| (float)Math.Round(Position.Y)); |
| |
| // Perform further collisions with the new bounds. |
| bounds = BoundingRectangle; |
| } |
| } |
| else |
| { |
| isOnSlope = false; |
| } |
| if (collision == TileCollision.SlopeRight) |
| { |
| if (isOnSlope) |
| { |
| if (isJumping == false) |
| { |
| // Resolve the collision along the Y axis. |
| Position = new Vector2 |
| (Position.X, slopeTopRight); |
| Position = new Vector2 |
| ((float)Math.Round(Position.X), |
| (float)Math.Round(Position.Y)); |
| |
| // Perform further collisions with the new bounds. |
| bounds = BoundingRectangle; |
| } |
| } |
| } |
| else |
| { |
| isOnSlope = false; |
| } |
| } |
| } |
| //slope loop |
| for (int x = leftTile; x <= rightTile; ++x) |
| { |
| TileCollision collision = Level.GetCollision(x, bottomTile); |
| if (collision == TileCollision.SlopeLeft || |
| collision == TileCollision.SlopeRight) |
| { |
| isOnSlope = true; |
| } |
| } |
| |
| //left slope collision routine |
| if ((bounds.Center.X - bounds.Left) == 0) |
| { |
| slopeTopLeft = bounds.Bottom; |
| } |
| else if (bounds.Center.X - bounds.Left < 0) |
| { |
| if (isOnSlope == true) |
| { |
| continue; |
| } |
| else |
| slopeTopLeft = bounds.Bottom; |
| } |
| else |
| { |
| slopeTopLeft = |
| (bounds.Bottom - |
| (bounds.Center.X - bounds.Left) * |
| (float)Math.Sin(Math.Atan2 |
| (bounds.Height, (bounds.Center.X - bounds.Left)))); |
| |
| |
| slopeTopLeft -= 2.0f; |
| |
| isOnSlope = true; |
| |
| isOnGround = true; |
| } |
| |
| //right slope collision routine |
| if ((bounds.Center.X - bounds.Left) == 0) |
| { |
| slopeTopRight = bounds.Bottom; |
| } |
| else if (bounds.Center.X - bounds.Left < 0) |
| { |
| if (isOnSlope == true) |
| { |
| continue; |
| } |
| else |
| slopeTopRight = bounds.Bottom; |
| } |
| else |
| { |
| slopeTopRight = |
| (bounds.Bottom - |
| (bounds.Center.X - bounds.Left) * |
| (float)Math.Sin(Math.Atan2 |
| (bounds.Height, (bounds.Center.X - bounds.Left)))); |
| |
| |
| slopeTopRight -= 2.0f; |
| |
| isOnSlope = true; |
| |
| isOnGround = true; |
| } |
| |
| // Save the new bounds bottom. |
| previousBottom = bounds.Bottom; |
| } |
| } |