Jump to content
  • Advertisement
Sign in to follow this  
Ekim_Gram

Pong - Ball/Paddle collision and reflection UPDATE: how can i make it more accurate?

This topic is 4836 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

I realized today that I had never actually written a Pong game that did more than just bounce the ball off the paddle depending on it's angle. So while familiarizing myself with C# and the newish SdlDotNet API, I've decided to throw together yet another Pong clone. Here's my code snippet
		private void CheckCollision(Paddle paddle, Ball ball)
		{
			if (Engine.SpriteCollide(paddle._sprite, ball._sprite))
			{
				// Reverse the xVel
				ball.xVel = -ball.xVel;
				// Now find where exactly on the paddle the ball hits
				for (int i=0; i<6; i++)
				{
					if ((ball._sprite.Y <= ((paddle._sprite.Y + paddle._sprite.Height)/7)*(i+1))
					&& (ball._sprite.Y >= ((paddle._sprite.Y + paddle._sprite.Height)/7)*(i+2)))
						ball.yVel = -3+i;
				}
			}
There must be something wrong with the for loop. I've spent the past hour and a half trying to create a half-decent method for doing so and this is the best I could come up with. The ball's xVel is negated but the yVel is never changed from 0 (default). EDIT: Alright, new question, how can I made the code below in my second post more...I guess accurate, better so to speak? [Edited by - Ekim_Gram on August 21, 2005 3:39:35 PM]

Share this post


Link to post
Share on other sites
Advertisement
At a fast glance it seems like the less-than and greater-than comparisons are mixed up. If there's a collision on the paddle then the ball must be between two y-values, in other words (simplified):
ball.y >= paddle.y && ball.y <= paddle.y + paddle.height
It seems you're basically iterating through the y-values of the paddle to decide the resulting yVel of the collision? The first condition will always be less than the second condition, so the combined statement never returns true. Is that what's wrong (yVel is not changed)?
The statement (paddle._sprite.Y + paddle._sprite.Height)/7 is used in both conditions and is constant as long as the paddle does not move. So the multiplication by (i+1) results in a smaller value than the multiplication with (i+2).
Graphically (with the y-axis pointing downwards):

(section of the paddle)
(ball) | y1 = constant*(i+1)
. | ball.y is here
|
| y2 = constant*(i+2)

As you can see y2 > y1 so if the ball collided with the paddle section then the following must be true:
ball.y => y1 && ball.y <= y2
I'm not exactly sure what effect you want to achieve, but for your current code I would recommend switching the less-than and greater-than comparisons:

private void CheckCollision(Paddle paddle, Ball ball)
{
if (Engine.SpriteCollide(paddle._sprite, ball._sprite))
{
// Reverse the xVel
ball.xVel = -ball.xVel;
// Now find where exactly on the paddle the ball hits
for (int i=0; i<6; i++)
{
if ((ball._sprite.Y >= ((paddle._sprite.Y + paddle._sprite.Height)/7)*(i+1))
&& (ball._sprite.Y <= ((paddle._sprite.Y + paddle._sprite.Height)/7)*(i+2)))
ball.yVel = -3+i;
}
}


Share this post


Link to post
Share on other sites
Well...it works now, sorta. Now, no matter where on the paddle it hits, the yVel is the same no matter what. It's such a simple theory, I don't know why I can't get this correct.

Talk about going back to n00bism. *sigh*


Never mind, problem solved. I realized that the for loop was iterating even after the if statement proved true. I stuck a bool in there and now I have the following (temp) code for those of you still looking to learn:


private void CheckCollision(Paddle paddle, Ball ball)
{
if (Engine.SpriteCollide(paddle._sprite, ball._sprite))
{
// Reverse the xVel
ball.xVel = -ball.xVel;
bool C = true;
// Now find where exactly on the paddle the ball hits
for (int i=0; i<6; i++)
{
if ((ball._sprite.Y >= ((paddle._sprite.Y + paddle._sprite.Height)/7)*(i))
&& (ball._sprite.Y <= ((paddle._sprite.Y + paddle._sprite.Height)/7)*(i+1))
&& (C == true))
{
ball.yVel = (-3)+i;
C = false;
}
}
}
}

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You would be better using a break statement instead of the bool your currently using.


private void CheckCollision(Paddle paddle, Ball ball)
{
if (Engine.SpriteCollide(paddle._sprite, ball._sprite))
{
// Reverse the xVel
ball.xVel = -ball.xVel;
// Now find where exactly on the paddle the ball hits
for (int i=0; i= ((paddle._sprite.Y + paddle._sprite.Height)/7)*(i))
&& (ball._sprite.Y

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You would be better using a break statement instead of the bool your currently using.


private void CheckCollision(Paddle paddle, Ball ball)
{
if (Engine.SpriteCollide(paddle._sprite, ball._sprite))
{
// Reverse the xVel
ball.xVel = -ball.xVel;
// Now find where exactly on the paddle the ball hits
for (int i=0; i<6; i++)
{
if ((ball._sprite.Y >= ((paddle._sprite.Y + paddle._sprite.Height)/7)*(i))
&& (ball._sprite.Y <= ((paddle._sprite.Y + paddle._sprite.Height)/7)*(i+1)))
{
ball.yVel = (-3)+i;
break;
}
}
}
}



It worked in the preview, but when I posted it half the code dissappeared.

Share this post


Link to post
Share on other sites
Quote:
Original post by Ekim_Gram
Alright, new question, how can I made the code below in my second post more...I guess accurate, better so to speak?

To be honest I think you should try a slightly different approach. Since the paddle is linear it should be possible to calculate yVel depending on the offset coordinate of the ball compared to the middle of the paddle. The further the ball is from the middle (the larger the offset coordinate is) the higher speed it gets. At least that's one common way to do it, it might be worth trying out and it will be a little faster than an iteration (it's not much of a performance hit though [grin])

Consider the following code:

private void CheckCollision(Paddle paddle, Ball ball)
{
if (Engine.SpriteCollide(paddle._sprite, ball._sprite))
{
// Reverse the xVel
ball.xVel = -ball.xVel;

//calculate the offset coordinate of the ball compared to the middle of the paddle
double offsetY = ball._sprite.Y - (paddle._sprite.Y + paddle._sprite.Height / 2.0);
//set the y-velocity
//explicit type casting might be needed here depending on what datatype yVel is
//offsetY / (paddle._sprite.Height / 2) is a value between -1 and 1
//3.0 is the maximum speed and is multiplied by that value
ball.yVel = offsetY / (paddle._sprite.Height / 2) * 3.0;
}
}



What do you think, could this work in your case?

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!