Jump to content
  • Advertisement
Sign in to follow this  
SonicD007

Why isn't my top and bottom collision detection working

This topic is 3152 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

I've been working on the collision detection for three days straight now trying to get it right and it just refuses to cooperate. I've posted years ago about this problem because back then I couldn't figure it out and now I still can't. Back then I was having trouble with the side collision (I can do that now) however the top and bottom collisions I still can't get to work. I've written this on paper numerous times trying to see the steps my code is going through but I just can't get it. The language is C++, using windows api, and using Visual Studio 2008 prof ed. Also I know I need to test for the dx and dy change as well so the ball doesn't jump through into the paddle, but with these tests the ball should still have a top and bottom collision which just isn't happening.
void HandleCollision(int direction)
{
	switch (direction)
	{
	case 1:
	case 3:
		g_Ball.dx *= -1;
		g_Ball.dy *= -1;
		break;

	case 2:
	case 4:
		g_Ball.dx *= -1;
		break;
	}

}

int TestForCollision(OBJECT a, OBJECT b)
{
	int left1, left2;
	int right1, right2;
	int top1, top2;
	int bottom1, bottom2;
	left1 = a.x;
	left2 = b.x;
	right1 = a.x + a.w;
	right2 = b.x + b.w;
	top1 = a.y;
	top2 = b.y;
	bottom1 = a.y + a.h;
	bottom2 = b.y + b.h;

	 if ( (top1 <= bottom2) && (bottom1 >= top2) )
	{
		if ( (right1 >= left2) && (right1 <= right2) )	//right side collision
		{
			return 2;
		}

		if ( (left1 <= right2) && (left1 >= left2) )	//left side collision
		{
			return 4;
		}
	}

	 else if ( (left1 <= right2) && (right1 >= left2) )
	{
		if ( (bottom1 >= top2) && (bottom1 <= bottom2) )	//top collision
		{
			return 1;
		}

		if ( (top1 <= bottom2) && (top1 >= top2) )	//bottom collision
		{
			return 3;
		}
	}
    return 0;
}

Share this post


Link to post
Share on other sites
Advertisement
I suggest you split your code into TestCollisionVertical and TestCollisionHorizontal functions. Your left/right collision test is blocking the top/bottom test via your "else if".

Share this post


Link to post
Share on other sites
Changing the else if to if still doesn't solve the problem. (changing the else if to if would basicly be the same as making a new function)

Share this post


Link to post
Share on other sites
When you say it is not working, what do you mean by that. Is the function returning a value you were not expecting? I.e. you are seeing the ball coming from top hitting the paddle, but the function is saying that the collision occurred from the left ?

I am suspecting this to be the case, under the assumption that your 'Ball' is of smaller size then your 'Peddle', and also your ball will be Object A and paddle Object B.

As you can see in your logic the condition

if ( (top1 <= bottom2) && (bottom1 >= top2) )

is satisfied even when the ball is colliding from the top (thus as TimmyC says, it is hiding the elseif logic in all the cases). Now if you look further down in that code path

if ( (left1 <= right2) && (left1 >= left2) )

is also satisfied when the ball is colliding from the top, and thus the function would be returning a 4.Thus changing else if to 'if' is not the same as splitting it up in two functions, as the elseif/if code path might not be executed because of return statements in the if above it.

Note : I have taken a very cursory look at your code, and I could be horribly wrong. The best solution for you would be to put a break point in the function and step through it in the debugger while observing the values of left right etc, and checking the calculations to make sure the logic means what you think it means (for example you might have just got confused regarding the y axis, i.e. whether it goes top(0) - bottom(100) or bottom(0) - top(100).

Share this post


Link to post
Share on other sites
The way you've currently got things, 'top' and 'bottom' collisions will only work if OBJECT a is wider than OBJECT b, and it's colliding in such a way that the left and right edges of OBJECT a are outside the left and right edges of object B. Otherwise, it'll be considered a left or right collision.

I'm pretty sure this approach is a non-starter. What should happen when the ball collides with the corner of the paddle? What should happen when the ball collides near the corner of the paddle? The corner is the point at which the collision result should change from one type to the other, no? Yet if you picture what the rectangles look like in a 'top-near-the-corner' collision and a 'left-near-the-corner' collision, they're very similar; all the tests you're performing here would come out the same way for both situations.

I think you'll have more luck with an approach like this:


// If A is off to any one side of B, it's not colliding. If it's not off to any of the sides, then it *must* be colliding - there are no other options.
if(top1 > bottom2 || bottom1 < top2 || left1 > right2 || right1 < left2) return 0;

// Work out the centers of the two boxes.
int centerX1 = (left1 << 1) + (right1 << 1),
centerX2,= (left2 << 1) + (right2 << 1),
centerY1 = (top1 << 1) + (bottom1 << 1),
centerY2 = (top2 << 1) + (bottom2 << 1);

// Work out the vector from the center of A to the center of B.
int deltaX = centerX2 - centerX1,
deltaY = centerY2 - centerY1;

// Scale this vector so that it's relative to the size of B.
float fX = deltaX / (float)b.w;
float fY = deltaY / (float)b.h;

// Check which direction the vector is pointing in.
if(abs(fX) > abs(fY))
return (fX > 0) ? 2 : 4;
else
return (fY > 0) ? 1 : 3;

Share this post


Link to post
Share on other sites
I appreciate all the help everyone. I've gotten the collision detection working now for the most part. I haven't run into any problems with a corner collision but there is a minor problem where if the player continues moving up while the ball is above it the ball would end up inside the paddle. I have a usable fix that for now is good enough for what I'm doing.

Thanks for taking the time to post that code superpig. I've been busy with schoolwork and whatnot but I'm going to try to look into that code a little more to understand what's going on. It has sparked an idea on how I can implement the angle hits on the ball so you've helped me get one step closer to finishing this :)

I'm almost done! Thank you all very much!

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!