Archived

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

DyDx

ball and paddle collision detection!

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

\
/
\
/
\

Share this post


Link to post
Share on other sites
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)


Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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());
}
}
}

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites