Jump to content
  • Advertisement
Sign in to follow this  
Svalorzen

Collision Detection Problem

This topic is 3030 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello everybody! I'm kind of going crazy over an absurd problem of collision detection. Basically, the system ( which is HGE ) reports a collision when my player box is standing on the floor ( player_box.low_y = floor.high_y ). This not only does not make any sense, but the same result does not happen when I hardcode two boxes one standing over the other, so I don't really know what to think.. This is my code:
void Fighter::think () {
    // H COLLISIONS HANDLING
    hgeRect fTry = fSpace;				// Copies Fighter bounding box
    // hSpeed > 0 :     RIGHT
    // hSpeed = 0 :     NOT MOVING
    // hSpeed < 0 :     LEFT
    float hSpeed = fSoul.getDx();		// Gets Fighter horizontal speed

    if ( hSpeed != 0 ) {				// If there is a possible collision to manage..

        // Projects Self into the Future
        if ( hSpeed > 0 )				// Expands the bounding box in the moving direction
            fTry.x2 += hSpeed;
        else
            fTry.x1 += hSpeed;

        // if cannot go there ( foreach square TODO )
        if ( fTry.Intersect( &rightWall ) ) {
            // Limits hSpeed
            if ( hSpeed > 0 )
                fSoul.setDx( rightWall.x1 - fSpace.x2 );	// Limits speed to space between Fighter and the wall
            else
                fSoul.setDx( rightWall.x2 - fSpace.x1 );
        }

    }

    // V COLLISIONS HANDLING
    fTry = fSpace;						// Resets try bounding box
    // vSpeed > 0 :     FALLING
    // vSpeed = 0 :     NOT MOVING
    // vSpeed < 0 :     RAISING
    float vSpeed = fSoul.getDy();		// Gets Fighter vertical speed

    if ( vSpeed != 0 ) {				// If there is a possible collision to manage..
										// NOTE: Due to gravity, vSpeed is usually never 0; at least 0.3
        // Projects Self into the Future
        if ( vSpeed > 0 )
            fTry.y2 += vSpeed;
        else
            fTry.y1 += vSpeed;

        // Cannot go there ( foreach square TODO )
        if ( fTry.Intersect( &floor ) ) {
            // FLOW ENTERS HERE EVEN THOUGH IT SHOULDN'T
            // Limits hSpeed
            if ( vSpeed > 0 ) {
                fSoul.setDy( floor.y1 - fSpace.y2 );
                // Resets Available Jumps
                fJumps = N_JUMPS;
            }
            else ; // AND ENDS UP HERE
                // commented this because otherwise my sprite vanishes =P
                // fSoul.setDy( floor.y2 - fSpace.y1 );
        }
    }
}

The handling for the horizontal and vertical part are exactly the same, but the problem rises when I try to jump after I'm landed on the floor. Then the game detects an intersection between my sprite and the floor, even though that is impossible ( I've debugged tracking all the variables.. ). It seems all right to me =( If you need additional information just let me know! Thanks in advance for any advices!

Share this post


Link to post
Share on other sites
Advertisement
One thing that comes to mind is floating point precision errors. If you have two floating point numbers (I assume that player_box.low_y and floor.high_y is floating point and not integers), you can't guarantee that the check (player_box.low_y == floor.high_y) returns true even if they seems to be equal. In the same way, you can't guarantee that player_box.low_y - floor.high_y returns 0, even if they are equal.

I had an error like that yesterday as well, and it took a while to find the problem (collisions were missed randomly, or so it seemed). I noticed that when my collision box' lower y value and the ground surface's y value were equal, the distance wasn't 0, it was something like 1e-15, or sometimes -1e-15 (or some other very small number).

So what you can try is what I did, do a "if (abs(player_box.low_y - floor.high_y) < 1e-12) distance = 0; else distance = player_box.low_y - floor.high_y;" on your distance calculations, and other floating point operations which may be sensitive to precision errors.

Hope this helps.

Edit: My numbers are based on double precision floats. Since you're using single precision floats, you might need a higher threshold.

Share this post


Link to post
Share on other sites
Also, if your sprite is subject to gravity, it might go like this: Sprite lands. Sprite is dragged down Y distance by gravity. Sprite is checked for a collision, which now exists. Sprite is moved up Y distance to resolve the collision.

From the computer's viewpoint, the sprite is always colliding. But, because the collision is fixed before the player can see it...

Edit: Nevermind, you check for that. Provided that check works, it shouldn't happen.

Share this post


Link to post
Share on other sites
Thanks for the heads up!

I've checked my code and these are the results:

- if I put a
if ( player_box.low_y != floor.high_y )
check_collision_code();
it works. ( but I cannot use this solution as it introduces a new couple of bugs, and it's also bad code which I really cannot stand )

- if I put a
if ( abs( player_box.low_y - floor.high_y ) < 1e-12 )
player_box.low_y = floor.high_y;
before the check collision code it still doesn't work, even though it actually enters the if.

There are another couple of things I didn't say about this problem:

1) I've debugged my code, and usually the variable watches signal when there is a problem with floats ( for example, my gravity offset is reported as 0.29999999998 ), but the Ys of the two boxes do not have any floating part.

2) If I set the floor bounding box a little more higher, let's say above 600, my code works. If I move the floor lower, at 700, the bug reappears. This could be related to non-integer movement; though to me it seems unlikely, because the limit that trigger the bug is precise ( 639 ).


Also, is there a way to automatically round floats to max 2 decimal digits? If I could do that I could avoid in block all this kind of problems..

Share this post


Link to post
Share on other sites
My first instinct there would be to check collision to make sure I'm checking against either all relative or all absolute positions and not, say, relative and absolute positions, somewhere.

Share this post


Link to post
Share on other sites
I'm sure I'm doing the check with the absolute position of every box, mostly because I never use a relative position for anything =P

Share this post


Link to post
Share on other sites
Could you post your intersect function and tell what x1,x2 and y1,y2 stand for?

Share this post


Link to post
Share on other sites
x1, y1 stand for the coordinates of the top-left vertex of the box.
x2, y2 stand for the coordinates of the bottom-right vertex of the box.

The intersection function is not mine, it's the one written in the HGE engine, so I think it's correct.

I've found the bug though.
It's here, when I expand the fighter's box:


if ( vSpeed > 0 )
fTry.y2 += vSpeed;
else
fTry.y1 += vSpeed; // This triggers the bug with the intersection


Now I've found it.. but still this line shouldn't trigger a collision downwards!

Ideas?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!