Pong. Reflection of ball intersecting paddle

Started by
8 comments, last by Thomas Wiborg 8 years, 9 months ago

Hello all,

I have a newbie question.

Im using Monogame/XNA to make a Pong clone.

I want to reflect my ball when it hits the paddle. If it hits the middle i want it to reflect horizontaly. The closer it get to the edges i want it to reflect sharper and sharper.

How can this be done EASILY? ive tried using angle/radians etc, but i just cant get the hang of it. Can i use any of the C#/XNA/Monogames inbuilt library to do this? Or is there some other way?

Ive googled up and down, but i cant find any article that is easily explained :)

Ofc, when it reflects and hits the wall i want it to keep the angle untill it hits the other paddle.

Thanks for all replies!

//Thomas Wiborg

Advertisement

If you use a vector for the direction the ball is moving you can set the it directly depending on where the ball hit on the paddle. As a start get how far from the center the ball hit the paddle. Set the balls direction vector to that value in x and then y to 1 so the ball moves up. Then normalize the vector. Now each time the ball hit the pad it will bounce of in direction only depending on where it hit the pad. This will also make the ball go straight up when it hits the middle of the pad :). You can fix that by changing so when it hits the middle of the pad it bounce only without changing direction.

@spinningcubes | Blog: Spinningcubes.com | Gamedev notes: GameDev Pensieve | Spinningcubes on Youtube

How can you check where the ball hits the paddle?

//Thomas Wiborg

I want to reflect my ball when it hits the paddle. If it hits the middle i want it to reflect horizontaly. The closer it get to the edges i want it to reflect sharper and sharper.

How can this be done EASILY? ive tried using angle/radians etc, but i just cant get the hang of it. Can i use any of the C#/XNA/Monogames inbuilt library to do this? Or is there some other way?

First, to reflect the ball you need the reflection vector formula.

Apply this formula with the direction of travel from the ball against the paddle's normal to get R. Examples:

Ball's direction of travel = Vector2( 0.707106781, 0.707106781 )

Paddle's normal = Vector2( -1, 0 )

R = D - 2 * dot( D, N ) * N = Vector2( -0.707106781, 0.707106781 )

Ball's direction of travel = Vector2( 1, 0 )

Paddle's normal = Vector2( -1, 0 )

R = D - 2 * dot( D, N ) * N = Vector2( -1, 0 )

Now, this may be a little uninteresting because the Paddle's normal is always (-1, 0) across the entire border (unless you hit the top and bottom). You may want to make it more interesting by interpolating the normal between two normals at the edges, like in this picture:

tlnvXDK.png

In black, the normals at the edges.

In orange, the interpolated normal finalNormal = lerp( A, B, W ) where A & B are the two normals, and W is a value between 0 and 1 where 0 means the ball is next to A, and 1 means the ball is next to B. Google how to write a lerp function (lerp stands for 'linear interpolation').

Make sure all your vectors are always normalized, lerp doesn't always return a normalized vector even if A & B are normalized. The reflection vector should be normalized if D and N already were, but it may not hurt to renormalize it.

You can also make it more interesting by skewing the normal slightly upwards or downwards based on the velocity at the paddle is moving, so that skilled users moving the paddle too fast will not reflect the ball 100% horizontally even when it hits the exact middle (it's a way to fake friction).

For a more unrealistic 'reflection' that is actually used in many implementations of paddle + ball game, you could just snap the balls new velocity to the vector from the center of the paddle to the center of the ball.

so upon intersection: ball.velocity = (ball.pos - paddle.pos).normalize() * ballSpeed;
This ofc, requires that the positions are at the center of the objects, or you have to calculate those points first.

Also, this aproach might give you too steep angles sometimes, so you could limit the outgoing velocity to some sensible angle. This is tweaking though. I recomend to just get it working first, and fix such issues later.

Programmer of HolyPoly games.

I want to reflect my ball when it hits the paddle. If it hits the middle i want it to reflect horizontaly. The closer it get to the edges i want it to reflect sharper and sharper.

How can this be done EASILY? ive tried using angle/radians etc, but i just cant get the hang of it. Can i use any of the C#/XNA/Monogames inbuilt library to do this? Or is there some other way?

First, to reflect the ball you need the reflection vector formula.

Apply this formula with the direction of travel from the ball against the paddle's normal to get R. Examples:

Ball's direction of travel = Vector2( 0.707106781, 0.707106781 )

Paddle's normal = Vector2( -1, 0 )

R = D - 2 * dot( D, N ) * N = Vector2( -0.707106781, 0.707106781 )

Ball's direction of travel = Vector2( 1, 0 )

Paddle's normal = Vector2( -1, 0 )

R = D - 2 * dot( D, N ) * N = Vector2( -1, 0 )

Now, this may be a little uninteresting because the Paddle's normal is always (-1, 0) across the entire border (unless you hit the top and bottom). You may want to make it more interesting by interpolating the normal between two normals at the edges, like in this picture:

tlnvXDK.png

In black, the normals at the edges.

In orange, the interpolated normal finalNormal = lerp( A, B, W ) where A & B are the two normals, and W is a value between 0 and 1 where 0 means the ball is next to A, and 1 means the ball is next to B. Google how to write a lerp function (lerp stands for 'linear interpolation').

Make sure all your vectors are always normalized, lerp doesn't always return a normalized vector even if A & B are normalized. The reflection vector should be normalized if D and N already were, but it may not hurt to renormalize it.

You can also make it more interesting by skewing the normal slightly upwards or downwards based on the velocity at the paddle is moving, so that skilled users moving the paddle too fast will not reflect the ball 100% horizontally even when it hits the exact middle (it's a way to fake friction).

Alot of great answers. But this was very good!

I have a question. Im using Monogame. So i have an inbuilt lerp function. MathHelper.Lerp(); (https://msdn.microsoft.com/en-us/library/microsoft.xna.framework.mathhelper.lerp.aspx)
And Vector2.Lerp() (https://msdn.microsoft.com/en-us/library/microsoft.xna.framework.vector2.lerp.aspx)

The thing is. The A and B.. is that the edges? And how should i insert them into this method? Since it parameters is float? And what is this Amount in the function?



//Thomas Wiborg

The thing is. The A and B.. is that the edges?

Yes, those are the black arrows from my picture. Their values are up to you (tweaked on game design).
The values I used in the graph were Vector2( -0.707106781, -0.707106781 ) and Vector2( -0.707106781, 0.707106781 ) which is basically a normalized normal inclined -45° and 45° respectively

And how should i insert them into this method? Since it parameters is float?

There is a version that takes a Vector2. But even if it weren't, you actually just need to lerp every component of the vector (X and Y coordinates) individually (in other words, two lerp calls).

And what is this Amount in the function?

A value between 0 and 1. Think of it like 0% and 100%.
You can use the distance in the Y component from the position of the ball to the bottom edge of the paddle divided by the height of the paddle to get the value in the [0; 1] range.

Now I did all the job for you. You have the tools now. Time for you to think it through, experiment and figure some the few remainders for yourself. We learn through failure, not success. I only helped you because you seemed really stuck.

The thing is. The A and B.. is that the edges?

Yes, those are the black arrows from my picture. Their values are up to you (tweaked on game design).
The values I used in the graph were Vector2( -0.707106781, -0.707106781 ) and Vector2( -0.707106781, 0.707106781 ) which is basically a normalized normal inclined -45° and 45° respectively

And how should i insert them into this method? Since it parameters is float?

There is a version that takes a Vector2. But even if it weren't, you actually just need to lerp every component of the vector (X and Y coordinates) individually (in other words, two lerp calls).

And what is this Amount in the function?

A value between 0 and 1. Think of it like 0% and 100%.
You can use the distance in the Y component from the position of the ball to the bottom edge of the paddle divided by the height of the paddle to get the value in the [0; 1] range.

Now I did all the job for you. You have the tools now. Time for you to think it through, experiment and figure some the few remainders for yourself. We learn through failure, not success. I only helped you because you seemed really stuck.

Thank you so much Matias. Yes I was EXTREMLY stuck :)
Ill give you a report on how its going :)

//Thomas Wiborg

I got things to work now... But there is something with the Vector2.Lerp() function...
I dont know what it is... But if I in the parameters set the angle to 150degree it bounces away at -140 when going up and -40 when going down. My incoming ball degree is 39

If I change the paramtere degree in the lerp function to 140degree it bounces away up -141 and down -39.

I test this with changing the amount in the lerp function from 0 to 1.

If I trie to set the angle to 170 it bounces up at -120 and down at -60... Isent this strange?

Also, the only way for me to get the angle sharper than -141 up and -39 down is to change the amount parameter in the lerp function to less than 0 and more than 1

Here is a pastebin of my code

http://pastebin.com/VkWMvTVa

//Thomas Wiborg

I got things to work now... But there is something with the Vector2.Lerp() function...
I dont know what it is... But if I in the parameters set the angle to 150degree it bounces away at -140 when going up and -40 when going down. My incoming ball degree is 39

If I change the paramtere degree in the lerp function to 140degree it bounces away up -141 and down -39.

I test this with changing the amount in the lerp function from 0 to 1.

If I trie to set the angle to 170 it bounces up at -120 and down at -60... Isent this strange?

Also, the only way for me to get the angle sharper than -141 up and -39 down is to change the amount parameter in the lerp function to less than 0 and more than 1

Here is a pastebin of my code

http://pastebin.com/VkWMvTVa

Looks like i fixed it.

R = D - 2 * dot( D, N ) * N

My D was wrong inside dot. :)

//Thomas Wiborg

This topic is closed to new replies.

Advertisement