Advertisement Jump to content
Sign in to follow this  

Collision between moving ball against brick (2d)

This topic is 4931 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! 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 this post

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

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

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using, you agree to our community Guidelines, Terms of Use, and Privacy Policy. 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!