Public Group

# box collision detection help needed

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

## Recommended Posts

Hi guys,

Working with SDL, on a simple scenario. A box is placed in the center of a screen, and a ball is set bouncing back and forth. Here's the code...

bool check_collision(SDL_Rect box1, SDL_Rect box2){

if(box1.x+box1.w<=box2.x)return false;

if(box1.x>=box2.x+box2.w)return false;

if(box1.y+box1.h<=box2.y)return false;

if(box1.y>=box2.y+box2.h)return false;

return true;
}


The "box" is the ball in this case


if(check_collision(box,the_obstacle)){//if the ball hits the obstacle

if(box.y+box.h>=the_obstacle.y)//if the ball is above the box
dy=-dy;
else if(the_obstacle.y+the_obstacle.h>=box.y)//if the ball is on the bottom of the box
dy=-dy;
if(box.x+box.w>=the_obstacle.x)//if the ball is on the right side
dx=-dx;
else if(the_obstacle.x+the_obstacle.w>=box.x)//if the ball is on the left side
dx=-dx;

}


I need for the ball to bounce differently, depending on which side of the box it hits. So, for example, if it hits top and bottom, dy must change, if it his the sides, dx must change. I tried many differnt ways, but I can't get it to work properly and don't understand what I am doing wrong. Any help would be greate appriciated.

If the above is unclear, imagine super mario brothers. If Mario hits the bottom of a brock, he come back down at the speed of gravity. If Mario lands on top of a brick, he is suspended, if he hits the sides of the brick, he falls back in a different manner.

Thanks,

Mike

##### Share on other sites

One solution is to move your ball in one direction 1st (on the x-axis), then check for collision; if it hit, inverse the ball's speed.  Then do it again for the y-axis.

##### Share on other sites

You do not exactly say what does not work as you want.

So what BeerNutts said. Plus, depending on the speed you use on the ball you can get stuck-in-box behaviour, as you simply toggle the delta instead of forcing the direction outside.

Like this:

if(box.y+box.h>=the_obstacle.y)
{
//if the ball is above the box
dy = -abs( dy );
}
else if(the_obstacle.y+the_obstacle.h>=box.y)
{
//if the ball is on the bottom of the box
dy = abs( dy );
}
if(box.x+box.w>=the_obstacle.x)
{
//if the ball is on the right side
dx = abs( dx );
}
else if(the_obstacle.x+the_obstacle.w>=box.x)
{
//if the ball is on the left side
dx = -abs( dx );
}

##### Share on other sites

The issue right now is, when the ball bounces off the obstacle, it comes back at the same angle as it came in.

Sorry BeerNuts, but I don't understand. I am propelling the ball forward like so...

	if(check_collision(box,the_obstacle)){//if the ball hits the obstacle

if(box.y+box.h>=the_obstacle.y)//if the ball is above the box
dy=-dy;
else if(the_obstacle.y+the_obstacle.h>=box.y)//if the ball is on the bottom of the box
dy=-dy;
if(box.x+box.w>=the_obstacle.x)
dx=-dx;
else if(the_obstacle.x+the_obstacle.w>=box.x)
dx=-dx;

}
box.x+=dx;//here's the movement
box.y+=dy;


##### Share on other sites

With your code as is, you are running into situations where the ball is inside the box, so the checks to see if the ball is within the boxes x limits evaluate to true, but so do the checks for the y limits. So, you need to force the ball back to its previous location ( outside the box ) before you start flipping any value.

bool check_collision(SDL_Rect box1, SDL_Rect box2){

if(box1.x+box1.w<=box2.x)return false;

if(box1.x>=box2.x+box2.w)return false;

if(box1.y+box1.h<=box2.y)return false;

if(box1.y>=box2.y+box2.h)return false;

return true;
}
if(check_collision(box,the_obstacle)){//if the ball hits the obstacle

box.x -= dx;
box.y -= dy;

if(box.y+box.h >= the_obstacle.y)//if the ball is above the box
dy=-dy;
else if(the_obstacle.y+the_obstacle.h >= box.y)//if the ball is on the bottom of the box
dy=-dy;
if(box.x+box.w >= the_obstacle.x)//if the ball is on the right side
dx=-dx;
else if(the_obstacle.x+the_obstacle.w >= box.x)//if the ball is on the left side
dx=-dx;

}
box.x+=dx;//here's the movement
box.y+=dy;


Here's a basic fix. Once we find out theres a collision, we move the ball back outside of the box, then check for which side of the box it is on and adjust the x and y velocity accordingly. If the ball is moving extremely fast, this can produce a slingshot effect in some cases. For instance: if the balls velocity is 10 pixels a frame, and it is 6 pixels from the wall, it will register a collision, move back to its position 6 pixels away, then be moved another 10. So in one frame it appears to have moved 22 pixels (6 to the wall, 6 away, then 10 more because of it's velocity). That would never be noticed with low velocities though. So you could either not adjust the balls position by it's velocity after a collision, or use Endurion's suggestion.

##### Share on other sites

Thanks for the aid Jdean300, but it's still not working. The ball keeps bouncing back in the same direction.

This collision detection is a nightmare.

##### Share on other sites
if(check_collision(box,the_obstacle)){//if the ball hits the obstacle

box.x -= dx;
box.y -= dy;

if(box.y+box.h >= the_obstacle.y && box.x > the_obstacle.x && box.x < the_obstacle.x+the_obstacle.w)
dy=-dy;
else if(the_obstacle.y+the_obstacle.h >= box.y && box.x > the_obstacle.x && box.x < the_obstacle.x+the_obstacle.w)
dy=-dy;
if(box.x+box.w >= the_obstacle.x && box.y > the_obstacle.y && box.y < the_obstacle.y + the_obstacle.h )
dx=-dx;
else if(the_obstacle.x+the_obstacle.w >= box.x && box.y > the_obstacle.y && box.y < the_obstacle.y + the_obstacle.h )
dx=-dx;

}


What I'm guessing is happening is when the ball is moved to its previous position, it's touching the wall (just touching, not inside), so that the adjacent sides' collision check still gets called.

I think that the above code will fix what's happening. We are checking to make sure that the ball is in front of the side that we check a collision for.

##### Share on other sites

Thanks JDean300. I won't be back home until very late tonight and then I will definetly try out your change. Of course, I will let you know what happened. Thanks a lot for the help.

Is there some generally accepted, well written box collision code that 2D gamers use for different sides hitting? I would think something like that gets used all the time.

Thanks,

Mike

##### Share on other sites

This is what I mean:

void Ball:Update(float deltaTime)
{
// assume current position is XLocation, YLocation, and velocity is XVelocity and YVelocity
float previousXLocation = XLocation;
float previousYLocation = YLocation;

// move ball in X direction
XLocation += XVelocity * deltaTime;

// Check if it hit
if (CheckCollision()) {
// move ball back to previous location, and inverse speed
XLocation = previousXLocation;
XVelocity = -XVelocity;
}

// Do same thing with Y direction

// move ball in Y direction
YLocation += YVelocity * deltaTime;

// Check if it hit
if (CheckCollision()) {
// move ball back to previous location, and inverse speed
YLocation = previousYLocation;
YVelocity = -YVelocity;
}


Make sense?

##### Share on other sites

Thanks for the help guys, Jdean300 has managed to solve my problem. I do understand your code now BeerNuts, and will try to rewrite it your way and see if I can get the same result as Jdean300 (which is working correctly).

Thanks again guys, you've been great help!

Mike

1. 1
2. 2
Rutin
16
3. 3
4. 4
5. 5

• 26
• 11
• 9
• 9
• 11
• ### Forum Statistics

• Total Topics
633702
• Total Posts
3013450
×