Jump to content
  • Advertisement
Sign in to follow this  
too_many_stars

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.

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

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 this post


Link to post
Share on other sites
Advertisement

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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!