开发者

Help understanding code snippet (AABB collision)

I've snatched this piece of tile collision code from another g开发者_运维问答ame, but in the spirit of understanding and not just stealing, I'd like to get some help understanding what exactly it does. Specifically what the function of x1, y1, x2, y2 are and why it picks start and end one tile outside the actual bounding box of the object.

...
    ...
        Int32 Tile.Size = 16;
    ...
...

...
    private Vector2 CheckTileCollision(Vector2 velocity)
    {
        // Find all the tiles we intersect with, including a layer outside.
        Int32 startx = (Int32)((Single)this.Left / Tile.Size) - 1;
        Int32 endx = (Int32)((Single)this.Right / Tile.Size) + 1;
        Int32 starty = (Int32)((Single)this.Top / Tile.Size) - 1;
        Int32 endy = (Int32)((Single)this.Bottom / Tile.Size) + 1;

        // The following are array positions, not world positions.
        Int32 x1 = -1; // Only set when there's a horizontal collision
        Int32 y1 = -1; // Only set when there's a horizontal collision
        Int32 x2 = -1; // Only set when there's a vertical collision
        Int32 y2 = -1; // Only set when there's a vertical collision

        Vector2 newVelocity = velocity;
        Vector2 nextPosition = this.position + velocity;

        for (Int32 x = startx; x <= endx; x += 1)
        {
            for (Int32 y = starty; y <= endy; y += 1)
            {
                if (realm.TileAt(x, y).IsSolid) // We only collide with solid tiles.
                {
                    // The world coordinates of a tile.
                    Vector2 tilePosition = new Vector2(x * Tile.Size, y * Tile.Size);

                    // Check if we intersect the tile.
                    if (nextPosition.X + this.Width > tilePosition.X &&
                        nextPosition.X < tilePosition.X + Tile.Size &&
                        nextPosition.Y + this.Height > tilePosition.Y &&
                        nextPosition.Y < tilePosition.Y + Tile.Size)
                    {
                        realm.Tiles[x, y].Debug = true;
                        if (this.Bottom <= tilePosition.Y) // if the bottom is above or touching the tile top
                        {
                            x2 = x; // x2 is set to current tile array position, not world position
                            y2 = y; // y2 is set to current tile array position, not world position

                            if (x2 != x1)
                                newVelocity.Y = tilePosition.Y - (position.Y + this.Height);
                        }
                        else if (this.Right <= tilePosition.X) // if the right side is to the left or touching the tile left
                        {
                            x1 = x; // x1 is set to current tile array position, not world position
                            y1 = y; // y1 is set to current tile array position, not world position

                            if (y1 != y2) 
                                newVelocity.X = tilePosition.X - (position.X + this.Width);
                            if (x2 == x1)
                                newVelocity.Y = this.Velocity.Y;
                        }
                        else if (this.Left >= tilePosition.X + Tile.Size)// if the left side is to the right or touching the tile right
                        {
                            x1 = x; // x1 is set to current tile array position, not world position
                            y1 = y; // y1 is set to current tile array position, not world position

                            if (y1 != y2)
                                newVelocity.X = (tilePosition.X + Tile.Size) - position.X;
                            if (x2 == x1)
                                newVelocity.Y = this.Velocity.Y;
                        }
                        else if (this.Top >= tilePosition.Y + Tile.Size) // if the top is below or touching the tile bottom
                        {
                            x2 = x; // x2 is set to current tile array position, not world position
                            y2 = y; // y2 is set to current tile array position, not world position

                            newVelocity.Y = (tilePosition.Y + Tile.Size) - position.Y;
                            if (y2 == y1)
                                newVelocity.X = this.Velocity.X;
                        }
                    }
                }
            }
        }
    return newVelocity;
}
...

EDIT

Added a few more comments to the code, and fixed up the ifs.


It picks start and end tiles outside of the bounding box of the object because the object could be moving, and has a velocity.

x1, y1, x2, y2 are the outside boundaries of the object, after it has resolved collisions.

The function returns a new velocity of the object that will prevent the object from colliding.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜