1
\$\begingroup\$

I'm having a certain problem when doing collision checks on bounding boxes that have their edges aligned with upper or right tiles. It shouldn't count as an intersection but I don't know a good solution for this.

Let's say the player is centered with some tile with that has no collision and the 8 surrounding tiles do have collision. The problem that happens here is that my collision check function will still report a collision because the upper and right edges of the square are in touch with the other tiles. The lower and left are too, but they won't collide:

The player surrounded by tiles with collision

I check the collision using the center and size, x and y, for the box.

bool isColliding( float centerX, float centerY, float sizeX, float sizeY );

So in this image, the player would be centered at ( 1.5, 1.5 ), relatively to tiles, and his size would be 1 tile x and y. That makes him centered in tile ( 1, 1 ). And when we do the math his left and lower limits are 1, so his limits are within tile ( 1, 1 ), but his upper and right limits are 2 so it reports an intersection with those tiles (the darker ones in the picture).

This happens because I calculate half sizes:

float halfSizeX = sizeX / 2.0f;

And the left limit would be

int leftLimit = centerX - halfSizeX;

In this case the player is not supposed to be intersecting any tile, so my quick fix was to subtract a very small value to the half size like this:

float halfSizeX = sizeX / 2.0f - 0.001f;

So the right limit will be 1.999f or so, and won't actually be 2. And this will work as this is only done in the collision checking, not in correcting the position, and all amounts of movement are bigger than 0.001 tiles which would be the biggest concern.

But I don't really like this solution, it looks kind of dirty.. My questions is, is there any good alternative to subtracting this value out of the blue?

EDIT:

As asked below in the comments I'm posting the code:

bool Map::isColliding( float centerX, float centerY, float sizeX, float sizeY )
{
    float halfSizeX = sizeX / 2.0f - 0.001f;
    float halfSizeY = sizeY / 2.0f - 0.001f;

    int fromX = (int)max( centerX - halfSizeX , 0.0f );
    int toX = (int)min( centerX + halfSizeX, (float)getNumTilesX() );

    int fromY = (int)max( centerY - halfSizeY , 0.0f );
    int toY = (int)min( centerY + halfSizeY, (float)getNumTilesY() );

    for ( int x = fromX; x <= toX; ++x ) {
        for ( int y = fromY; y <= toY; ++y ) {
            if ( getTile( x, y )->hasCollision() ) {
                return true;
            }
        }
    }

    return false;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ The manner in which you've approached collision is not, in my opinion, the simplest method. Regardless, the problem likely lies elsewhere. Changing the dimensions of bounding boxes to non-whole numbers is the wrong way to go 9/10 times. Post your collision detection code itself. I'll bet that's where the problem is. \$\endgroup\$ – igrad Jun 29 '14 at 20:36
  • \$\begingroup\$ What would be a simpler method? \$\endgroup\$ – aslg Jun 30 '14 at 9:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.