Ví dụ được cung cấp bởi Microsoft dường như nếu phát hiện va chạm (từ những gì tôi có thể thấy) sẽ có một lỗi nhỏ. Khi người dùng va chạm với một ô Không thể vượt qua, độ sâu của giao lộ được tính toán. Giá trị độ sâu X và Y nhỏ hơn được sử dụng để cố định vị trí của người dùng để nó không còn va chạm với ô. Nhưng nếu người dùng đang di chuyển theo đường chéo thì điều này có thể dẫn đến việc người dùng không kết thúc chính xác tại điểm mà nhân vật sẽ va chạm đầu tiên với gạch không?
Tôi có thể sai nhưng đó chỉ là cách tôi nhìn thấy nó.
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;
// 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 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)
{
// 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.
{
// 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;
}
}
}
}
}
// Save the new bounds bottom.
previousBottom = bounds.Bottom;
}