// Checks for collisions between the character and the level's tiles, and handles these collisions when needed. void HandleTileCollisions(Vector2 previousPosition) { isGrounded = false; standingOnIceTile = false; standingOnHotTile = false; // determine the range of tiles to check Rectangle bbox = BoundingBoxForCollisions; Point topLeftTile = level.GetTileCoordinates(new Vector2(bbox.Left, bbox.Top)) - new Point(1, 1); Point bottomRightTile = level.GetTileCoordinates(new Vector2(bbox.Right, bbox.Bottom)) + new Point(1, 1); for (int y = topLeftTile.Y; y <= bottomRightTile.Y; y++) { for (int x = topLeftTile.X; x <= bottomRightTile.X; x++) { Tile.Type tileType = level.GetTileType(x, y); // ignore empty tiles if (tileType == Tile.Type.Empty) { continue; } // ignore platform tiles if the player is standing below them Vector2 tilePosition = level.GetCellPosition(x, y); if (tileType == Tile.Type.Platform && localPosition.Y > tilePosition.Y && previousPosition.Y > tilePosition.Y) { continue; } // if there's no intersection with the tile, ignore this tile Rectangle tileBounds = new Rectangle((int)tilePosition.X, (int)tilePosition.Y, Level.TileWidth, Level.TileHeight); if (!tileBounds.Intersects(bbox)) { continue; } // calculate how large the intersection is Rectangle overlap = CollisionDetection.CalculateIntersection(bbox, tileBounds); // if the x-component is smaller, treat this as a horizontal collision if (overlap.Width < overlap.Height) { if ((velocity.X >= 0 && bbox.Center.X < tileBounds.Left) || // right wall (velocity.X <= 0 && bbox.Center.X > tileBounds.Right)) // left wall { localPosition.X = previousPosition.X; velocity.X = 0; } } // otherwise, treat this as a vertical collision else { if (velocity.Y >= 0 && bbox.Center.Y < tileBounds.Top && overlap.Width > 6) // floor { isGrounded = true; velocity.Y = 0; localPosition.Y = tileBounds.Top; // check the surface type: are we standing on a hot tile or an ice tile? Tile.SurfaceType surface = level.GetSurfaceType(x, y); if (surface == Tile.SurfaceType.Hot) { standingOnHotTile = true; } else if (surface == Tile.SurfaceType.Ice) { standingOnIceTile = true; } } else if (velocity.Y <= 0 && bbox.Center.Y > tileBounds.Bottom && overlap.Height > 2) // ceiling { localPosition.Y = previousPosition.Y; velocity.Y = 0; } } } } }