Archived

This topic is now archived and is closed to further replies.

Drizzt DoUrden

Pong - Ball to Paddle Detection

Recommended Posts

Over the last few weeks, I have been testing collision detection methods out, and learning how to use SDL and C++ in a way that would be speedy and accurate. I came up with this function for my collisions -
  
//bounding box collision detection

bool CheckCollision(int x1, int x2, int x3, int x4, int y1, int y2, int y3, int y4)
{
	if((x2 >= x3) && (x4 >= x1) && (y2 >= y3) && (y4 >= y1))
	{
		return true;
	}
	else
	{
		return false;
	}
}
  
It''s incredibly accurate, but not exactly the fastest method. I like it though. But I am now working on a Pong clone - how original - and I need to check circle-rectangle collision rather than rectangle-rectangle. I am not exactly sure how to go about doing this. I am using Simple DirectMedia Layer, and the two paddles are 64x64 bitamps, while the ball is a 32x32 bitmap. I could just use use 24x24 out of the 32x32 of the bitmap, and then the rectangles would be detected, but it sort of under-detects in that way. I am just wondering if someone has a suggested method that is accurate and speedy for a circle to rectangle collision. Thanks in advance. ------------------------------ Simple DirectMedia Layer:
Main Site - (www.libsdl.org) Cone3D Tutorials- (cone3D.gamedev.net) GameDev.net''s Tutorials - (Here)
OpenGL:
Main Site - (www.opengl.org) NeHe Tutorials - (nehe.gamedev.net) Online Books - (Red Book) (Blue Book)

Share this post


Link to post
Share on other sites
You have a bunch of options. One is to test using a bounding box (not terribly accurate, but often sufficient). Another is to test using vectors: if your circle is of radius R and moves along a path P (which is always a straight line but changes directions after collisions), then if the distance of the center of the circle from the surface of the paddle (any of the flat edges) is less than R , you have a collision.

Nasty. Why? Because if you test at regular intervals, it is conceivably possible for the ball to be moving fast enough to skip right over the paddle. SO what you do is you modify the above. You use some vector math to determine if and where the ball will collide with a surface (including the barriers) and keep moving it until that time. Since Pong is two-dimensional, that''s mostly solving simultaneous equations of lines.

If I''m not clear, either post here again or email me.

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!

Share this post


Link to post
Share on other sites
I understand what you mean, completely. I just don't know the code for it. Basically, I have the idea of what needs to be done, but I have no idea how to implement it in code. How do I check if a radius/diameter is overlapping a rectangle?

------------------------------
Simple DirectMedia Layer:

Main Site - (www.libsdl.org)
Cone3D Tutorials- (cone3D.gamedev.net)
GameDev.net's Tutorials - (Here)

OpenGL:

Main Site - (www.opengl.org)
NeHe Tutorials - (nehe.gamedev.net)
Online Books - (Red Book) (Blue Book)


Edited by - Drizzt DoUrden on January 12, 2002 12:15:03 AM

Share this post


Link to post
Share on other sites
I guess you could also just figure out the x value where the ball would hit a paddle (which will be the same if the paddles simply move vertically). Then, when the ball reaches that x value, determine whether and where the paddle connected using the y values of the paddle and ball. This will save a LOT of computation time, but it will only work if the paddles are only moving along the sides of the field in a strictly vertical way.

--Ben Carter
Romans 8:38-39

Share this post


Link to post
Share on other sites
struct vector2d
{
float x, y;
};
.
struct pong_ball
{
vector2d position;
vector2d velocity;
};

Every time through your loop, you will add the x and y of velocity and position together to be the new ball position, then either leave velocity unchanged or flip them if we've hit a barrier. How do we know if we've hit a barrier? Observe.

There are two basic Pong barriers: the top and the bottom. For simplicity's sake, we'll say that the top barrier has a y-coordinate of 0 and the bottom one a y-coordinate of 100. We then want to know if the distance of the ball's center to a spot on the barrier along the line of our velocity is less than the radius.

Slope-Intercept Line Equation: y = mx + b (where b is an arbitrary intercept).
Another useful form of this equation is that
(y2 - y1) / (x2 - x1) = m
(yes, the same m)

A point we already know is on the line is the ball's center; (position.x, position.y) ie plugging it into the equation will yield the expected results. We need to find another point on the line but also on the barrier. If we take the lower barrier (y = 100),
(position.y - 100) / (position.x - X) = m
(again, the same m)

and the point (X, 100) is on the barrier and on the line of the velocity. We can then compute the Pyhtagorean distance from the center of the ball to the point:
distance = sqrt(    (position.y - 100)2 + (position.x - X)2)    
if(distance < radius)
{
// Houston, we have a problem!
}


So what's this mysterious m quantity? The slope of the velocity vector relative to the 2D cartesian axes. Where do we find it?

m = (position.y - vecloty.y) / (position.x - velocity.x);

Hope that was helpful.

[Edit:] Formatting.

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!


Edited by - Oluseyi on January 13, 2002 1:35:36 AM

Share this post


Link to post
Share on other sites
Thanks Oluseyi, I''ve got it working quite well right now. I''ve still got alittle work to do - scoring, wnning and losing screens, etc. When it''s done, I''ll post it in the announcements forums if I''m not banned after the ''contest'' on the front page.

------------------------------
Simple DirectMedia Layer:

Main Site - (www.libsdl.org)
Cone3D Tutorials- (cone3D.gamedev.net)
GameDev.net''s Tutorials - (Here)

OpenGL:

Main Site - (www.opengl.org)
NeHe Tutorials - (nehe.gamedev.net)
Online Books - (Red Book) (Blue Book)

Share this post


Link to post
Share on other sites
Heh. Sorry for reviving on old topic, but I just got (very) up to speed on this Pong project I've been putting off for too long now, and I'm having trouble with my collisions. Here is a link to my downloadable "game".

I'm using a boolean function

    
bool CheckCollision(int bX, int bY, int pX, int pY)
{
if((bY + 32 >= pX) && (pX + 32 >= bX) && (bY + 32 >= pY) && (pY + 32 >= bY))
{
return true;
}
else
{
return false;
}
}


with a boolean variable to check it (bool collided). Here's what I'm doing inside of the loop:

       
collided = CheckCollision(destBall.x, destBall.y, destBarOne.x, destBarOne.y);
if(collided == true)
{
dx = -dx;
if(dx < 15)
{
dx += 3;
}
}
collided = CheckCollision(destBall.x, destBall.y, destBarTwo.x, destBarTwo.y);
if(collided == true)
{
dx = -dx;
if(dx < 15)
{
dx += 3;
}
}


As for dest (I'm using SDL, I don't know how it works in DirectDraw...):

       
destBarTwo.x = 540;
destBarTwo.y = 240;

destBarOne.x = 20;
destBarOne.y = 240;


All right. Now, when I change BarTwo's value's to 20 and 40, the collision test works. for some reason, it won't check 540! It just ignores it. I don't understand why. Does anyone see something wrong?

Thanks in advance.





------------------------------
Simple DirectMedia Layer:

Main Site - (www.libsdl.org)
Cone3D Tutorials- (cone3D.gamedev.net)
GameDev.net's Tutorials - (Here)

OpenGL:

Main Site - (www.opengl.org)
NeHe Tutorials - (nehe.gamedev.net)
Online Books - (Red Book) (Blue Book)


Edited by - Drizzt DoUrden on February 5, 2002 10:12:33 PM

Share this post


Link to post
Share on other sites
First thought, what are the types of the coordinates? If they''re unsigned chars, then the highest value they can hold is 255. I''ll keep looking, but if that''s the problem, see if that fixes it all.

[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]
Thanks to Kylotan for the idea!

Share this post


Link to post
Share on other sites
quote:
Original post by Drizzt DoUrden
if((bY + 32 >= pX) && (pX + 32 >= bX) && (bY + 32 >= pY) && (pY + 32 >= bY))

Your first conditional is mismatched (bY and pX).

[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]
Thanks to Kylotan for the idea!

Share this post


Link to post
Share on other sites
So
(bY + 32 >= pX)

should be

(pX >= bY + 32)

I don't see why. The left paddle's collision works great. The right paddle's doesn't.

------------------------------
Simple DirectMedia Layer:

Main Site - (www.libsdl.org)
Cone3D Tutorials- (cone3D.gamedev.net)
GameDev.net's Tutorials - (Here)

OpenGL:

Main Site - (www.opengl.org)
NeHe Tutorials - (nehe.gamedev.net)
Online Books - (Red Book) (Blue Book)



Edited by - Drizzt DoUrden on February 5, 2002 10:26:27 PM

Share this post


Link to post
Share on other sites
Hmm. You were right! Thanks a bunch

------------------------------
Simple DirectMedia Layer:

Main Site - (www.libsdl.org)
Cone3D Tutorials- (cone3D.gamedev.net)
GameDev.net''s Tutorials - (Here)

OpenGL:

Main Site - (www.opengl.org)
NeHe Tutorials - (nehe.gamedev.net)
Online Books - (Red Book) (Blue Book)

Share this post


Link to post
Share on other sites