# Collision between moving ball against brick (2d)

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

## Recommended Posts

Hi! I am making this Breakout clone and was wondering if someone could help me with collision detection between a moving ball and a brick (in 2d). The one I have pretty much suck. It's neither effective nor robust. It should give me point of intersection so I could change the response direction of the ball. The respone should be different if I hit an edge than if I hit a corner (the brick's corner normals should be [1, 1], [1, -1] and so on). This collision detection should also work when the velocity is parallell to the brick's edges and when it is moving in a 45 degree angle (because of the corner normals). Could someone please help me? [Edited by - Azaykon on July 23, 2005 6:54:53 PM]

##### Share on other sites
One thing to realize is the corner normal won't always be at a 45-degree angle, but rather will be the vector from the ball center to the corner, which will vary depending on where exactly the ball hits.

Anyway, I assume the bricks are axis-aligned? The function you describe isn't too hard to implement, but I wouldn't say it's easy either. As you note, it takes some care to make it robust. Even with a robust implementation, you may still miss collisions and end up with initial interpenetration, so it's a good idea to handle those cases as well.

The complete function is a little much to describe here. Can you post what you have already? Maybe it can be tweaked to give the desired results...

##### Share on other sites
Below you will find the code.

The first part I cast the flippped ballVelocity vector from each of the corners to see if I hit the ball. If it find
a hit, a hit is marked, hit time is saved and planeNormal (which is used for ball response) is set to that specific corner normal.

Then I have used an example taken from Olii where he showed how we find intersection between a point and an AABB. What I have done, is to use this example to check top/right/bottom/left side of the ball. (I guess there is a better way to do this, when you're checking a ball against AABB instead of a point).

As it is, the ball finds collisions with the bricks and changes direction differently when it hits corners, but as
I said earlier there are times when the ball just pass through bricks. So if you folks could help making it more effective and robust that would be cool :-).

bool Ball::isBallIntersectingBrick(Brick* brick, D3DXVECTOR2 ballVelocity,						   D3DXVECTOR2& planeNormal, float& hitTime)	{	bool isHit = false;	//Create an AABB and set it equal to the brick	Aabb box = brick->getAabb();	//Check if the ball hits any of the brick's corners	D3DXVECTOR2 corner[4];	corner[0] = D3DXVECTOR2(box.min.x, box.min.y); //Left upper corner	corner[1] = D3DXVECTOR2(box.max.x, box.min.y); //Right upper corner	corner[2] = D3DXVECTOR2(box.max.x, box.max.y); //Right lower corner	corner[3] = D3DXVECTOR2(box.min.x, box.max.y); //Left lower corner	D3DXVECTOR2 cornerNormal[4];	cornerNormal[0] = D3DXVECTOR2(-1.0f,  1.0f); //Left upper corner	cornerNormal[1] = D3DXVECTOR2( 1.0f,  1.0f); //Right upper corner	cornerNormal[2] = D3DXVECTOR2( 1.0f, -1.0f); //Right lower corner	cornerNormal[3] = D3DXVECTOR2(-1.0f, -1.0f); //Left lower corner		D3DXVec2Normalize(&cornerNormal[0], &cornerNormal[0]);	D3DXVec2Normalize(&cornerNormal[1], &cornerNormal[1]);	D3DXVec2Normalize(&cornerNormal[2], &cornerNormal[2]);	D3DXVec2Normalize(&cornerNormal[3], &cornerNormal[3]);	//Flip the ballVelocity vector	D3DXVECTOR2 flippedVelocity = (-1.0f * ballVelocity);	for(int j = 0; j < 4; j++)		{		D3DXVECTOR2 m = corner[j] - _position; //_position is center of ball				float a = D3DXVec2Dot(&flippedVelocity, &flippedVelocity);		float b = D3DXVec2Dot(&m, &flippedVelocity);		float c = D3DXVec2Dot(&m, &m) - _radius * _radius;		float discriminant = b * b - a * c;				if(discriminant >= 0.0f)			{			float t0 = (-b + ::sqrtf(discriminant)) / a;			float t1 = (-b - ::sqrtf(discriminant)) / a;			/*if(t0 > t1)				{ d3d::swap(t0, t1); }*/			if(t0 >= 0.0f && t0 <= hitTime)				{				isHit = true;				hitTime = t0;				planeNormal = cornerNormal[j];				}			if(t1 >= 0.0f && t1 <= hitTime)				{				isHit = true;				hitTime = t1;				planeNormal = cornerNormal[j];				}			}		}		D3DXVECTOR2 point1(0.0f, 0.0f);	//	D3DXVECTOR2 point2(0.0f, 0.0f); // 	D3DXVECTOR2 circleSide[4]; //Used to check with 4 sides of the ball			//Initialize the normals	circleSide[0] = D3DXVECTOR2( 0.0f,  1.0f); //Top     	circleSide[1] = D3DXVECTOR2( 1.0f,  0.0f); //Right	circleSide[2] = D3DXVECTOR2( 0.0f, -1.0f); //Bottom	circleSide[3] = D3DXVECTOR2(-1.0f,  0.0f); //Left		for(int i = 0; i < 4; i++)		{		point1 = _position + (_radius * circleSide);//_position is center of ball		point2 = point1 + ballVelocity;		float tXmin = (box.min.x - point1.x) / (point2.x - point1.x);		float tXmax = (box.max.x - point1.x) / (point2.x - point1.x);		float tYmin = (box.min.y - point1.y) / (point2.y - point1.y);		float tYmax = (box.max.y - point1.y) / (point2.y - point1.y);			float tX0 = min(tXmin, tXmax);		float tX1 = max(tXmin, tXmax);		float tY0 = min(tYmin, tYmax);		float tY1 = max(tYmin, tYmax);		float t0 = max(tX0, tY0);		float t1 = min(tX1, tY1);				if(t0 < t1 && (t0 >= 0.0f && t0 <= hitTime))			{			isHit = true;			hitTime = t0;			planeNormal.x = (hitTime == tXmin)? -1.0f : 							(hitTime == tXmax)? 1.0f : 0.0f;			planeNormal.y = (hitTime == tYmin)? -1.0f :							(hitTime == tYmax)? 1.0f : 0.0f;								}		}			if(isHit == true)		{ return true; }		return false;	}

[Edited by - Azaykon on July 24, 2005 6:52:21 AM]

1. 1
2. 2
Rutin
15
3. 3
4. 4
5. 5

• 9
• 9
• 14
• 12
• 10
• ### Forum Statistics

• Total Topics
633270
• Total Posts
3011156
• ### Who's Online (See full list)

There are no registered users currently online

×