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

Started by
5 comments, last by Ekim_Gram 18 years, 8 months ago
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]
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;		}	}
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;					}				}			}		}
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
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.
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?
Thanks man.

This topic is closed to new replies.

Advertisement