Why isn't my top and bottom collision detection working

Started by
4 comments, last by SonicD007 13 years, 11 months ago
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;
}

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".
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)
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).
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;

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

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!

This topic is closed to new replies.

Advertisement