ball and paddle collision detection!

Started by
8 comments, last by DyDx 21 years, 1 month ago
Hey all, I''m writing an SDL-based clone of Pong with extremely simple pixel-based graphics. I have it running except for collision detection between the paddles and ball - and unfortunately this is the one area I have never been able to successfully implement. The game is set-up with 2 paddles, with the height and width and the x,y center of the paddle available. The ball has an x,y center and a radius. The way I''ve attempted to approach the problem is by using a long if statement comparing the x,y position of the ball to the left and right edges of the paddle - if it is within the left and right edges of the paddle and it''s y position is close enough, reverse the y-velocity. In theory I thought it would work, if a bit oddly, but it actually just causes the ball to bounce back no matter what! Here is that portion of code:

	if((ball->getXPos() >= (player1->getXPos() - (0.5 * player1->getWidth())) || ball->getXPos() <= (player1->getXPos() + (0.5 * player1->getXPos())))
	&& ball->getYPos() >= (player1->getYPos() - (0.5 * player1->getHeight())))
	{
		ball->setYVel(-1 * ball->getYVel());
  } 
if someone could point out the flaw in my logic, or [preferably] a better, more realistic method, that''d be nice too! Thanks.
Advertisement
quote:Original post by DyDx
if it is within the left and right edges of the paddle and it''s y position is close enough, reverse the y-velocity.
*snip
	if((ball->getXPos() >= (player1->getXPos() - (0.5 * player1->getWidth())) || ball->getXPos() <= (player1->getXPos() + (0.5 * player1->getXPos())))*snip 




When you write it out in English, you say the ball is between the edges of the paddle (or the ball is less than the right side AND more than the left side)...

...but your code says OR, so your code only cares if the ball is EITHER to the right of the left side OR to the left of the right side.

Try changing || to && and see if that works
here is how i handled it in my first ever game


    if(theBall->xVel < 0) // ball is moving left{	if( (theBall->xPosition < leftPlayer.xPosition+leftPlayer.width) &&			theBall->xPosition > leftPlayer.xPosition)	{		if((theBall->yPosition+theBall->height > leftPlayer.yPosition) &&				theBall->yPosition < leftPlayer.yPosition+leftPlayer.height)		{				theBall->xVel = -theBall->xVel;				leftPlayer.iAmHit(); // used for power ups		}	}}else	// ball is moving right{	if((theBall->xPosition+theBall->width > rightPlayer.xPosition) &&		theBall->xPosition+theBall->width < rightPlayer.xPosition+rightPlayer.width)	{		if((theBall->yPosition+theBall->height > rightPlayer.yPosition) && 			theBall->yPosition < rightPlayer.yPosition+rightPlayer.height)		{			theBall->xVel = -theBall->xVel;			rightPlayer.iAmHit(); // used for power ups		}	}}  


[edited by - deal on March 2, 2003 1:57:11 PM]
Thanks ducki, I didn't notice that :D

Anyways, it works for the most part now, but I still have anomalies - specifically, when it hits the corner of the paddle. When this happens, either the ball just goes through the paddle OR the ball sort of slides through the paddle... hard to describe.

Here is the current code:

void checkCollisions(Ball *ball, Paddle *player1, Paddle *player2){	// check for collisions with player1	if((ball->getXPos() >= (player1->getXPos() - (0.5 * player1->getWidth())) && ball->getXPos() <= (player1->getXPos() + (0.5 * player1->getXPos())))	&& (ball->getYPos() + ball->getRadius()) >= (player1->getYPos() - (0.5 * player1->getHeight())))	{		ball->setYVel(-1 * ball->getYVel());  }  // check for collisions with player2  if((ball->getXPos() >= (player2->getXPos() - (0.5 * player2->getWidth())) && ball->getXPos() <= (player2->getXPos() + (0.5 * player2->getXPos())))	&& (ball->getYPos() - ball->getRadius()) <= (player2->getYPos() + (0.5 * player2->getHeight())))	{		ball->setYVel(-1 * ball->getYVel());  }}	 


Anyone else with tips?

Thanks.

[edited by - DyDx on March 2, 2003 2:03:30 PM]
I''d be willing to bet that the ball is slipping past because the XPos of the ball doesn''t take its radius into account.

Duplicate the bit about adding the ball.radius to its XPos just like you did for the YPos and that should detect the collision.
incorporate direction of ball into the collision detection similar to my code posted above.

what is happening is that the balls x velocity is constantly being reversed kinda like below

\
/
\
/
\
quote:Original post by ducki
I''d be willing to bet that the ball is slipping past because the XPos of the ball doesn''t take its radius into account.

Duplicate the bit about adding the ball.radius to its XPos just like you did for the YPos and that should detect the collision.


Hmm well I tried that:

void checkCollisions(Ball *ball, Paddle *player1, Paddle *player2){	// check for collisions with player1	if(((ball->getXPos() + ball->getRadius()) >= (player1->getXPos() - (0.5 * player1->getWidth())) && (ball->getXPos() - ball->getRadius()) <= (player1->getXPos() + (0.5 * player1->getXPos())))	&& (ball->getYPos() + ball->getRadius()) >= (player1->getYPos() - (0.5 * player1->getHeight())))	{		ball->setYVel(-1 * ball->getYVel());  }  // check for collisions with player2  if(((ball->getXPos() + ball->getRadius()) >= (player2->getXPos() - (0.5 * player2->getWidth())) && (ball->getXPos() - ball->getRadius()) <= (player2->getXPos() + (0.5 * player2->getXPos())))	&& (ball->getYPos() - ball->getRadius()) <= (player2->getYPos() + (0.5 * player2->getHeight())))	{		ball->setYVel(-1 * ball->getYVel());  }}	 


To no avail... it still goes through the paddle at corners and there is still weird sliding about on the bottom of the screen. (and sometimes the top)

I can send the executable and SDL.dll if anyone would care to see what I''m speaking about... the rar file is less than 700kb. (I can include all the source code too if you''d like)


quote:Original post by deal
incorporate direction of ball into the collision detection similar to my code posted above.

what is happening is that the balls x velocity is constantly being reversed kinda like below

\
/
\
/
\


Hmm I thought your method was about the same as mine, I guess I''ll have to examine it more closely. thanks.
try something like below


  void checkCollisions(Ball *ball, Paddle *player1, Paddle *player2){		// check for collisions with player1	if( /*code here to check ball is moving left*/)	{		if((ball->getXPos() >= (player1->getXPos() - (0.5 * player1->getWidth())) 			&& ball->getXPos() <= (player1->getXPos() + (0.5 * player1->getXPos())))				&& (ball->getYPos() + ball->getRadius()) >= (player1->getYPos() - (0.5 * player1->getHeight())))		{					ball->setYVel(-1 * ball->getYVel());  		}	}		// check for collisions with player2	else	{		if((ball->getXPos() >= (player2->getXPos() - (0.5 * player2->getWidth())) 			&& ball->getXPos() <= (player2->getXPos() + (0.5 * player2->getXPos())))				&& (ball->getYPos() - ball->getRadius()) <= (player2->getYPos() + (0.5 * player2->getHeight())))			{					ball->setYVel(-1 * ball->getYVel());  		}	}}  
quote:Original post by deal
try something like below


    void checkCollisions(Ball *ball, Paddle *player1, Paddle *player2){		// check for collisions with player1	if( /*code here to check ball is moving left*/)	{		if((ball->getXPos() >= (player1->getXPos() - (0.5 * player1->getWidth())) 			&& ball->getXPos() <= (player1->getXPos() + (0.5 * player1->getXPos())))				&& (ball->getYPos() + ball->getRadius()) >= (player1->getYPos() - (0.5 * player1->getHeight())))		{					ball->setYVel(-1 * ball->getYVel());  		}	}		// check for collisions with player2	else	{		if((ball->getXPos() >= (player2->getXPos() - (0.5 * player2->getWidth())) 			&& ball->getXPos() <= (player2->getXPos() + (0.5 * player2->getXPos())))				&& (ball->getYPos() - ball->getRadius()) <= (player2->getYPos() + (0.5 * player2->getHeight())))			{					ball->setYVel(-1 * ball->getYVel());  		}	}}    



After dealing with the mass of paranthesis, it works pretty damn well.

Thanks!

This topic is closed to new replies.

Advertisement