(Ping Pong) The ball gets stuck behind the paddle

Hello, everyone.
I’m a novice programmer and I’m new to SDL and I’m having some trouble with
my Ping Pong game. The biggest issue being that the ball sometimes gets hit
back, but most of the time it just gets stuck behind the paddle.

I’m using SDL_HasIntersection(); to check if the ball (the Ball struct
contains a SDL_Rect) collides with the paddle (the Paddle struct contains a
SDL_Rect), if that happens, this method inside the Ball struct is called:

void Ball::Rebound(const SDL_Rect & paddle_rect, SDL_Rect & sadursme,
Mix_Chunk *& gLow)
{
SDL_IntersectRect(&getRect(), &paddle_rect, &sadursme);
float relX = (paddle_rect.x + 40) - sadursme.x;
float normX = relX / 40;
float angle = normX * MAX_ANGLE;
xVel = BALL_VEL * cos(angle);
yVel = BALL_VEL * sin(angle);
Mix_PlayChannel( -1, gLow, 0 );
}

I’m guessing the problem is that the ball actually goes inside the paddle
(this is when it gets stuck behind the paddle) and the Rebound method keeps
getting called, but I’ve yet come up with a solution.

Any help or advice is welcome!

Bernard–
View this message in context: http://sdl.5483.n7.nabble.com/Ping-Pong-The-ball-gets-stuck-behind-the-paddle-tp39741.html
Sent from the SDL mailing list archive at Nabble.com.

As an experienced (possibly too experienced) crafter of breakout games, I can tell you the immediate and simple solution to your problem is this:

Use a for loop for moving the ball, in no more than 1 pixel increments (I.E. do a for loop on BALL_VEL, and just add the cos and sin of the angle each step), doing your intersect check and other
physics every loop iteration.

This means that the ball will never go more than 1 pixel into the paddle (or bricks or any other obstacles you implement), the classification of what to do in response to a collision that is only 1
pixel deep, is relatively straightforward.On 02/27/2014 01:39 PM, bernardlv wrote:

Hello, everyone.
I’m a novice programmer and I’m new to SDL and I’m having some trouble with
my Ping Pong game. The biggest issue being that the ball sometimes gets hit
back, but most of the time it just gets stuck behind the paddle.

I’m using SDL_HasIntersection(); to check if the ball (the Ball struct
contains a SDL_Rect) collides with the paddle (the Paddle struct contains a
SDL_Rect), if that happens, this method inside the Ball struct is called:

void Ball::Rebound(const SDL_Rect & paddle_rect, SDL_Rect & sadursme,
Mix_Chunk *& gLow)
{
SDL_IntersectRect(&getRect(), &paddle_rect, &sadursme);
float relX = (paddle_rect.x + 40) - sadursme.x;
float normX = relX / 40;
float angle = normX * MAX_ANGLE;
xVel = BALL_VEL * cos(angle);
yVel = BALL_VEL * sin(angle);
Mix_PlayChannel( -1, gLow, 0 );
}

I’m guessing the problem is that the ball actually goes inside the paddle
(this is when it gets stuck behind the paddle) and the Rebound method keeps
getting called, but I’ve yet come up with a solution.

Any help or advice is welcome!

Bernard


View this message in context: http://sdl.5483.n7.nabble.com/Ping-Pong-The-ball-gets-stuck-behind-the-paddle-tp39741.html
Sent from the SDL mailing list archive at Nabble.com.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


LordHavoc
Author of DarkPlaces Quake1 engine - http://icculus.org/twilight/darkplaces
Co-designer of Nexuiz - http://alientrap.org/nexuiz
"War does not prove who is right, it proves who is left." - Unknown
"Any sufficiently advanced technology is indistinguishable from a rigged demo." - James Klass
"A game is a series of interesting choices." - Sid Meier

Your problem is tunneling. It’s a well known thing.
The solution that Forest Hale suggests will work, yes, but it’s going to be
horribly slow. Which is why physics engines use other methods.
Try Box2D. It solves your problem and it isn’t as slow as what Forest
suggests.On 28 February 2014 00:04, Forest Hale wrote:

As an experienced (possibly too experienced) crafter of breakout games, I
can tell you the immediate and simple solution to your problem is this:

Use a for loop for moving the ball, in no more than 1 pixel increments
(I.E. do a for loop on BALL_VEL, and just add the cos and sin of the angle
each step), doing your intersect check and other
physics every loop iteration.

This means that the ball will never go more than 1 pixel into the paddle
(or bricks or any other obstacles you implement), the classification of
what to do in response to a collision that is only 1
pixel deep, is relatively straightforward.

On 02/27/2014 01:39 PM, bernardlv wrote:

Hello, everyone.
I’m a novice programmer and I’m new to SDL and I’m having some trouble
with
my Ping Pong game. The biggest issue being that the ball sometimes gets
hit
back, but most of the time it just gets stuck behind the paddle.

I’m using SDL_HasIntersection(); to check if the ball (the Ball struct
contains a SDL_Rect) collides with the paddle (the Paddle struct
contains a
SDL_Rect), if that happens, this method inside the Ball struct is called:

void Ball::Rebound(const SDL_Rect & paddle_rect, SDL_Rect & sadursme,
Mix_Chunk *& gLow)
{
SDL_IntersectRect(&getRect(), &paddle_rect, &sadursme);
float relX = (paddle_rect.x + 40) - sadursme.x;
float normX = relX / 40;
float angle = normX * MAX_ANGLE;
xVel = BALL_VEL * cos(angle);
yVel = BALL_VEL * sin(angle);
Mix_PlayChannel( -1, gLow, 0 );
}

I’m guessing the problem is that the ball actually goes inside the paddle
(this is when it gets stuck behind the paddle) and the Rebound method
keeps
getting called, but I’ve yet come up with a solution.

Any help or advice is welcome!

Bernard


View this message in context:
http://sdl.5483.n7.nabble.com/Ping-Pong-The-ball-gets-stuck-behind-the-paddle-tp39741.html
Sent from the SDL mailing list archive at Nabble.com.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


LordHavoc
Author of DarkPlaces Quake1 engine -
http://icculus.org/twilight/darkplaces
Co-designer of Nexuiz - http://alientrap.org/nexuiz
"War does not prove who is right, it proves who is left." - Unknown
"Any sufficiently advanced technology is indistinguishable from a rigged
demo." - James Klass
"A game is a series of interesting choices." - Sid Meier


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

My solution is quite fast I can assure you in the context of a pong or breakout game - the number of iterations is a few per frame and you’ve got known data that can be instantly retrieved (rects to
compare).

I used this method with great success on far less powerful computers (think 68000 @ 7MHz) in past games while running plenty of other code.

Box2D has a better empirical solution to the problem but bruteforce is quite okay at low iterations due to the few operations required per iteration, and in the hands of a new and learning programming
it is a more flexible and malleable approach.

P.S. I have written and physics engines, do not underestimate their per-iteration costs :)On 02/27/2014 03:41 PM, Ivan Rubinson wrote:

Your problem is tunneling. It’s a well known thing.
The solution that Forest Hale suggests will work, yes, but it’s going to be horribly slow. Which is why physics engines use other methods.
Try Box2D. It solves your problem and it isn’t as slow as what Forest suggests.

On 28 February 2014 00:04, Forest Hale <@Forest_Hale mailto:Forest_Hale> wrote:

As an experienced (possibly too experienced) crafter of breakout games, I can tell you the immediate and simple solution to your problem is this:

Use a for loop for moving the ball, in no more than 1 pixel increments (I.E. do a for loop on BALL_VEL, and just add the cos and sin of the angle each step), doing your intersect check and other
physics every loop iteration.

This means that the ball will never go more than 1 pixel into the paddle (or bricks or any other obstacles you implement), the classification of what to do in response to a collision that is only 1
pixel deep, is relatively straightforward.

On 02/27/2014 01:39 PM, bernardlv wrote:
> Hello, everyone.
> I'm a novice programmer and I'm new to SDL and I'm having some trouble with
> my Ping Pong game. The biggest issue being that the ball sometimes gets hit
> back, but most of the time it just gets stuck behind the paddle.
>
> I'm using SDL_HasIntersection(); to check if the ball (the Ball struct
> contains a SDL_Rect) collides with the paddle (the Paddle struct contains a
> SDL_Rect), if that happens, this method inside the Ball struct is called:
>
> void Ball::Rebound(const SDL_Rect & paddle_rect, SDL_Rect & sadursme,
> Mix_Chunk *& gLow)
> {
>     SDL_IntersectRect(&getRect(), &paddle_rect, &sadursme);
>     float relX = (paddle_rect.x + 40) - sadursme.x;
>     float normX = relX / 40;
>     float angle = normX * MAX_ANGLE;
>     xVel = BALL_VEL * cos(angle);
>     yVel = BALL_VEL * sin(angle);
>     Mix_PlayChannel( -1, gLow, 0 );
> }
>
> I'm guessing the problem is that the ball actually goes inside the paddle
> (this is when it gets stuck behind the paddle) and the Rebound method keeps
> getting called, but I've yet come up with a solution.
>
> Any help or advice is welcome!
>
> Bernard
>
>
>
> --
> View this message in context: http://sdl.5483.n7.nabble.com/Ping-Pong-The-ball-gets-stuck-behind-the-paddle-tp39741.html
> Sent from the SDL mailing list archive at Nabble.com.
> _______________________________________________
> SDL mailing list
> SDL at lists.libsdl.org <mailto:SDL at lists.libsdl.org>
> http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
>


--
LordHavoc
Author of DarkPlaces Quake1 engine - http://icculus.org/twilight/darkplaces
Co-designer <http://icculus.org/twilight/darkplaces Co-designer> of Nexuiz - http://alientrap.org/nexuiz
"War does not prove who is right, it proves who is left." - Unknown
"Any sufficiently advanced technology is indistinguishable from a rigged demo." - James Klass
"A game is a series of interesting choices." - Sid Meier

_______________________________________________
SDL mailing list
SDL at lists.libsdl.org <mailto:SDL at lists.libsdl.org>
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


LordHavoc
Author of DarkPlaces Quake1 engine - http://icculus.org/twilight/darkplaces
Co-designer of Nexuiz - http://alientrap.org/nexuiz
"War does not prove who is right, it proves who is left." - Unknown
"Any sufficiently advanced technology is indistinguishable from a rigged demo." - James Klass
"A game is a series of interesting choices." - Sid Meier

well if the ball has its own velocity, you can create a new SDL_Rect with x and y according to the current velocity and check the intersection, and then do the collision code. that way it would be just before hitting the target.

In a similar vein, if the ball has its own velocity, you can optimize the collision checking pretty easily.? Let’s say the paddle is vertical, and so its X never changes.

if (ball.x - ball.velocityX > paddle.x + paddle.width)
? return false; //it’s automatically not a collision

MasonOn Thursday, February 27, 2014 5:08 PM, javierecf wrote:

well if the ball has its own velocity, you can create a new SDL_Rect with x and y according to the current velocity and check the intersection, and then do the collision code. that way it would be just before hitting the target.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Why not just use a sweep test?

http://supertux.lethargik.org/wiki/Sweep_collision_algorithms

Another simple way to handle this is to kick the ball out of the paddle’s
rect. However you do that is probably fine, from just setting the x-coord
of the ball to the right side of the paddle or to using the velocity to
find the collision point and using that.

Jonny D

I’m very grateful for all of the replies that I’ve gotten but I have to
apoligize to be sort of a letdown to you guys / to be in need for more help.
I spent quite some time going over the replies and I looked into the sweep
collision algorithm in multiple websties, but I didn’t really get it… I
have the ball’s movement speed (velocity), can calculate the distance
between the ball and paddle, but I don’t know what to do with the “time” I
get by deviding the distance by the speed. I just got frustrated in the end.
I’m just new to this and am probably having a bad day, sorry.

Forest Hale wrote

Use a for loop for moving the ball, in no more than 1 pixel increments
(I.E. do a for loop on BALL_VEL, and just add the cos and sin of the angle
each step), doing your intersect check and other physics every loop
iteration.

I’m sorry, but I don’t really understand how to implement that into my code.
This is how I move the ball (the paddles in my game are horizontal):

void Ball::Draw(SDL_Renderer* gRenderer){
SDL_Rect ball;
ball.x = posX;
ball.y = posY;
ball.w = BALL_WIDTH;
ball.h = BALL_HEIGTH;

SDL_SetRenderDrawColor(gRenderer, 0, 255, 255, 0);
SDL_RenderDrawRect(gRenderer, &ball);
thisBall = ball; // "thisBall" is the ball (SDL_Rect) which is available

in the object.
}

void Ball::Update(int& score1, int& score2)
{
posX += xVel;
posY += yVel;

if(posX + 10 > 480 || posX + 10 < 0) xVel = -xVel; // If either side of the

“table” is hit.

// If the player or the computer doesn’t reflect the ball.

if(posY + 10 > 548)
{
    score1++;
    yVel = -yVel;
}

if(posY + 10 < 0)
{
    score2++;
    yVel = -yVel;
}

}

javierecf wrote

well if the ball has its own velocity, you can create a new SDL_Rect with
x and y according to the current velocity and check the intersection, and
then do the collision code. that way it would be just before hitting the
target.

Just to clarify - you’re suggesting to make another ball (ball2) which is
solely for calculations and always is one xVel and yVel increment further
than the visible ball to check for collision?–
View this message in context: http://sdl.5483.n7.nabble.com/Ping-Pong-The-ball-gets-stuck-behind-the-paddle-tp39741p39775.html
Sent from the SDL mailing list archive at Nabble.com.

In the collision function you should use a new sdl rect, instead of the
normal one for the ball. Not another ball.On Mar 1, 2014 5:15 AM, “bernardlv” wrote:

I’m very grateful for all of the replies that I’ve gotten but I have to
apoligize to be sort of a letdown to you guys / to be in need for more
help.
I spent quite some time going over the replies and I looked into the sweep
collision algorithm in multiple websties, but I didn’t really get it… I
have the ball’s movement speed (velocity), can calculate the distance
between the ball and paddle, but I don’t know what to do with the “time” I
get by deviding the distance by the speed. I just got frustrated in the
end.
I’m just new to this and am probably having a bad day, sorry.

Forest Hale wrote

Use a for loop for moving the ball, in no more than 1 pixel increments
(I.E. do a for loop on BALL_VEL, and just add the cos and sin of the
angle
each step), doing your intersect check and other physics every loop
iteration.

I’m sorry, but I don’t really understand how to implement that into my
code.
This is how I move the ball (the paddles in my game are horizontal):

void Ball::Draw(SDL_Renderer* gRenderer){
SDL_Rect ball;
ball.x = posX;
ball.y = posY;
ball.w = BALL_WIDTH;
ball.h = BALL_HEIGTH;

SDL_SetRenderDrawColor(gRenderer, 0, 255, 255, 0);
SDL_RenderDrawRect(gRenderer, &ball);
thisBall = ball; // "thisBall" is the ball (SDL_Rect) which is

available
in the object.
}

void Ball::Update(int& score1, int& score2)
{
posX += xVel;
posY += yVel;

    if(posX + 10 > 480 || posX + 10 < 0) xVel = -xVel; // If either

side of the
"table" is hit.

// If the player or the computer doesn’t reflect the ball.

    if(posY + 10 > 548)
{
    score1++;
    yVel = -yVel;
}

if(posY + 10 < 0)
{
    score2++;
    yVel = -yVel;
}

}

javierecf wrote

well if the ball has its own velocity, you can create a new SDL_Rect with
x and y according to the current velocity and check the intersection, and
then do the collision code. that way it would be just before hitting the
target.

Just to clarify - you’re suggesting to make another ball (ball2) which is
solely for calculations and always is one xVel and yVel increment further
than the visible ball to check for collision?


View this message in context:
http://sdl.5483.n7.nabble.com/Ping-Pong-The-ball-gets-stuck-behind-the-paddle-tp39741p39775.html
Sent from the SDL mailing list archive at Nabble.com.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

javierecf wrote

In the collision function you should use a new sdl rect, instead of the
normal one for the ball. Not another ball.

Yes, sorry, not sure why I wrote that.
I had a similar idea for the AiPaddle - to make it move accordingly to a
coefficient of the ball’s velocity, but that didn’t really work out too
well, neither making a new SDL_Rect to check for the collision. It’s even
worse like that, previously the ball would budge out of being stuck, but
with the new SDL_Rect it just dissapears sometimes.–
View this message in context: http://sdl.5483.n7.nabble.com/Ping-Pong-The-ball-gets-stuck-behind-the-paddle-tp39741p39777.html
Sent from the SDL mailing list archive at Nabble.com.

The adaptation I was suggesting is that you set xVel and yVel to cos and sin of the angle, but not multiplied by BALL_VEL at all.

And then you update posX and posY in a loop, also calling the rect intersect function and handling collisions in that loop.

So your ball moves (hypothetically) 10 times per frame, but for no more than 1 pixel each time, so when a collision is detected, it’s only 1 pixel into the paddle and the response becomes easy.

Assuming your ball position and velocity are floats, you can easily use *0.1f on the steps and just do a loop for 10 iterations, something like:
for (i = 0; i < 10; i++)
{
posX += xVel * 0.1f;
posY += yVel * 0.1f;
if (SDL_HasIntersection(…)) // check if ball hit paddle
{
Rebound(…); // react to ball hitting paddle
}
}

Which means that your ball could only get a little bit into the paddle (not necessarily pixels but 1/10th as much as velocity).

Whereas my original suggestion steps the ball BALL_VEL times per frame for small (nearly 1 pixel) amounts and is thus marginally more efficient than a fixed amount like 10.–
LordHavoc
Author of DarkPlaces Quake1 engine - http://icculus.org/twilight/darkplaces
Co-designer of Nexuiz - http://alientrap.org/nexuiz
"War does not prove who is right, it proves who is left." - Unknown
"Any sufficiently advanced technology is indistinguishable from a rigged demo." - James Klass
"A game is a series of interesting choices." - Sid Meier

Forest Hale wrote

The adaptation I was suggesting is that you set xVel and yVel to cos and
sin of the angle, but not multiplied by BALL_VEL at all.

And then you update posX and posY in a loop, also calling the rect
intersect function and handling collisions in that loop.

So your ball moves (hypothetically) 10 times per frame, but for no more
than 1 pixel each time, so when a collision is detected, it’s only 1 pixel
into the paddle and the response becomes easy.

Assuming your ball position and velocity are floats, you can easily use
*0.1f on the steps and just do a loop for 10 iterations, something like:
for (i = 0; i < 10; i++)
{
posX += xVel * 0.1f;
posY += yVel * 0.1f;
if (SDL_HasIntersection(…)) // check if ball hit paddle
{
Rebound(…); // react to ball hitting paddle
}
}

Which means that your ball could only get a little bit into the paddle
(not necessarily pixels but 1/10th as much as velocity).

Whereas my original suggestion steps the ball BALL_VEL times per frame for
small (nearly 1 pixel) amounts and is thus marginally more efficient than
a fixed amount like 10.

I thought that would work, but it for some reason it doesn’t, worst being
that I don’t know why.
I tried javierecf’s suggestion before with another SDL_Rect to check for
collision before the actual ball gets to the paddle, it didn’t work for me
as well, but I think I’ll give it another try because I think that the
reason my game isn’t working is because the ball actually collides with the
paddle and then it just keeps getting nudged inside it.

If that doesn’t work I’m not sure if I have any other alternatives apart
from learning the sweep algorithm or quitting, lol. I’ll keep in mind all of
the suggestions for future projects, of course.–
View this message in context: http://sdl.5483.n7.nabble.com/Ping-Pong-The-ball-gets-stuck-behind-the-paddle-tp39741p39851.html
Sent from the SDL mailing list archive at Nabble.com.

Till now I didn’t offer my solution. What you have said makes me think I
should. If the speed of the ball is faster in one step then the width of
the paddle then you must test in small steps that are less than the width
of the paddle. You can simply place little test blocks along the way spaced
like this and test each one. So five times the speed means you have 5
blocks and then the ball. They should be just tiny blocks it’s no big deal
to test those for collision so it’s fast. I also make them visible for
diagnostics when the diagnostics flag is set to true I show those blocks
and also draw lines .