# Ping Pong - ball movement. Completely random, smooth, not 'locked' movement. How to?

• 08-21-2010
newn
Ping Pong - ball movement. Completely random, smooth, not 'locked' movement. How to?
Hi everyone. I took different library, which is much more advanced, and completely in C++ - SFML now, so i'm remaking Ping Pong game. Now i would like to do a smooth, nice movement, random movement...

I used to write the movement like that:

Code:

```        if (dir == 1 && y > 0)         {                 for(velocity_x = 0;velocity_x > -3; velocity_x --)                 {                         for(velocity_y = 0;velocity_y > -3; velocity_y --)                         {                         velocity_x --;                         velocity_y --;                         }                 }                 x -= vel_x - velocity_x;                 y -= vel_y - velocity_y;         }```
Which 'lags', and is not very smooth, looks crappy. I think about something like that, but i'm unable to make it work:

Before the hit to the wall or the stick, leave it constant. On hit generate a random number, for the direction, to which the ball would move. But how to make the direction work - i don't know. x++ and y-- ain't gonna work here.
• 08-21-2010
GReaper
I can't see why you do the above, end i can also see some potential errors to come!
• 08-21-2010
newn
Well, i did the above, because i don't know how else i can do it, that's what i've asked here. ;)

As for errors, well, there are 4 directions, everything works fine. But yea, Error's possible on different resolutions - as offscreen stuff. That was my Allegro code for Ping Pong's ball. Now i'm learning SFML, and rewriting the game for that.
• 08-21-2010
iMalc
What you posted is exactly equivalent to:
Code:

```        if (dir == 1 && y > 0)         {                 velocity_x = -4;                 velocity_y = -4;                 x -= vel_x - velocity_x;                 y -= vel_y - velocity_y;         }```
What effect were you expecting those loops to have?
• 08-21-2010
newn
Well, it's a little bit of acceleration effect.
Anyway, i'm not using the code i provided anymore, as i said in the first post - it's unrealistic, and have almost no randomness.
Is there any better way (maybe like i said here after the code) way to make the ball do more random movements, and don't come back, where it's been a sec ago?
• 08-21-2010
iMalc
You mean you want to do something other than exactly reflect its direction in any walls it encounters. Sure, you can vary the angle a few degrees.
However your first change must be switching from integer coordinates to floating or fixed-point coordinates.
Floating point coordinates means that your acceleration, velocity, position etc is all of type float or double.
Fixed-point means you still use integer math but the position needs to be bit-shifted before being drawn on screen. 16.16 fixed-point format would be a good choice.
Once you've made that switch then we can start discussing how to make it smoother, more realistic, or less predictable.
I see you've posted on other forums also.
• 08-21-2010
newn
Yes, i did.

Okay, so, floats sounds a little bit easier to me.
As you can see, i've got an answer there, but still - i don't get how it should work, it calculatesthe movement speed, not the angle...
Okay, here's some of my 6AM top logic, while i still haven't fallen on my keyboard (going to bed after this post):
So, i should make the angle randomize in a real small amounts - as you said - floats, maybe 3.60 value would be the max? Also, i should check, that the ball wouldn't fly directly towards the side wall, i mean just straith line, so i should exclude some degrees (i'm not perfect at math, hopefully, i'll get better this year.), then also on collision to a wall, or a paddle, i should randomize the value again, by excluding particular number of the degrees.
BUT i guess there's a much better way to do this, since as i think of this, this would be unnecesary code, which wouldn't work perfectly, and would be hard to maintain, also the program could take more resources, and i forgot one more thing i just had in mind a sec ago, can't remember... One more fact, that says "Go to bed already!".
So anyway, maybe i'll find a reply, when i wake up, which would give me a better tip, than i just gave myself.

Thanks, hopefully, you've understood, what i was talking about, lol.
• 08-22-2010
VirtualAce
For ball movement:

Code:

```ball.x += cosf(ball.angle) * ball.speed; ball.y += sinf(ball.angle) * ball.speed;```
As for hitting the walls there are several ways to do this. As long as your walls are all orthogonal to each other and you detect when a collision happens the response is simple. You can either reflect the velocity on x and y or you can compute the reflected angle. To compute the reflected angle you will need a triangle and some trig. To create the triangle:

• Subtract the point of collision from the initial point of the ball to get the hypotenuse
• Extend the y component of a vector from the point of collision towards the direction of the initial point of the ball to form a side.
• Extend the x component of a vector from the initial point of the ball towards the point of collision.
• sin = o / h cos = a / h tan = o / a
• Remember the entire formula is: sin(theta) = o / h, cos(theta) = a / h, and tan(theta) = o / a

You can also do this with vectors and can reflect the vector about the y or x axis depending on the point of collision. However this is much the same as simply reflecting x or y when you hit the wall.
If you want to get really fancy then you can use the normals of the walls and the velocity vector of the ball to compute the reflection vector. However in 2D the cross product is undefined so your normals will have to be pseduo-normals - IE: they are unit vectors that are orthogonal to the line or wall.
• 08-22-2010
newn
Thanks, i made it work. although, i not completely understand how it works. But i made it work, collision stuff works alright too, but i made it my way, by converting from Allegro's and adding some additional stuff to it from some example or something like that.

I would ask someone to explain me a few things, but i BET, that this wouldn't happen, because it would be like tutoring me maths and c++, and that stuff costs...

Anyway, thanks.
• 08-22-2010
VirtualAce
Then share with us how you did it.
• 08-22-2010
newn
Okay, here's how i did it (p.s. soon, i'll be asking for code optimization, so i will post the full source code.):

Code:

```// Collision stuff.                         if(SpriteBall.GetPosition().x < SpritePong1.GetPosition().x + SpritePong1.GetSize().x &&                           SpriteBall.GetPosition().x > SpritePong1.GetPosition().x + (SpritePong1.GetSize().x / 2.0f) &&                           SpriteBall.GetPosition().y + SpriteBall.GetSize().y >= SpritePong1.GetPosition().y &&                           SpriteBall.GetPosition().y <= SpritePong1.GetPosition().y + SpritePong1.GetSize().y)                         {                                 BallAngle = PI - BallAngle;                                 SpriteBall.SetX(SpritePong1.GetPosition().x + SpritePong1.GetSize().x + 0.1f);                         }                         if(SpriteBall.GetPosition().x + SpriteBall.GetSize().x > SpritePong2.GetPosition().x &&                           SpriteBall.GetPosition().x + SpriteBall.GetSize().x < SpritePong2.GetPosition().x + (SpritePong2.GetSize().x / 2.0f) &&                           SpriteBall.GetPosition().y + SpriteBall.GetSize().y >= SpritePong2.GetPosition().y &&                           SpriteBall.GetPosition().y <= SpritePong2.GetPosition().y + SpritePong2.GetSize().y)                         {                                 BallAngle = PI - BallAngle;                                 SpriteBall.SetX(SpritePong2.GetPosition().x - SpriteBall.GetSize().x - 0.1f);                         }                         if(SpriteBall.GetPosition().y < 0.f)                         {                                 BallAngle = -BallAngle;                                 SpriteBall.SetY(0.1f);                         }                         if(SpriteBall.GetPosition().y + SpriteBall.GetSize().y > 480.f)                         {                                 BallAngle = -BallAngle;                                 SpriteBall.SetY(480 - SpriteBall.GetSize().y - 0.1f);                         }                         if(SpriteBall.GetPosition().x < 0.f)                         {                                 GameRunning = false;                                 EndGame.SetText("Player 2 wins, congratulations!");                         }                         if(SpriteBall.GetPosition().x + SpriteBall.GetSize().x > App.GetView().GetRect().GetWidth())                         {                                 GameRunning = false;                                 EndGame.SetText("Player 1 wins, congratulations!");                         }                 }```
That's simple and understandable for me, not much maths required either. Easiest way... Usually, i take advanced ways, but I'm not quite good enough yet. I'll be optimizing and adding more functions to my game's code anyway, so maybe I'll be able to rewrite the code somehow later on...

x = std::cos(BallAngle) * Factor, y = std::sin(BallAngle) * Factor; // This' little longer, as it's in a library, but i wrote the point, the logic of it. It's just requires different definition, in that library, that's all.

Hmmm, this i don't understand. But i made it working.

Well, maybe i understand how it works, but i wouldn't be able to make such thing myself working, nor do i understand WHY it is so. Here's how i think it works:

It gets the cos and sin of ball's angle, then it multiplies it by ball's speed. Well... Is it supposed to get the value, and multiply it by speed, so it actually moves? Or it goes to that position? It looks like it's setting the position, where to move, not angle or stuff like that. Like clicking with a mouse on the screen, in a strategy game, then fetches the position and moves there.

I would really appreciate, if you could explain me this thing a little bit more, so i could understand it completely. Programming without understanding - is not programming. It's copying or being lucky. In my opinion
• 08-22-2010
VirtualAce
All those calculations fall apart when:

• Screen resolution changes
• Ball speed changes

Resolution should not be hard-coded. Query your system to grab the current screen or viewport width. For a D3D app the viewport info will always be the most accurate for both windowed and full screen mode.

Code:

```x += std::cos(BallAngle) * Factor, y += std::sin(BallAngle) * Factor```
Sinf() and cosf() from the CRT should suffice just fine. They are the floating point versions of sin and cos. Sin() and cos() are the double versions.

I don't quite understand your sentence concerning this code. This is essentially the parametric form of a line. I would advise you do some research on mathematical vectors.

The formula is essentially:
Final = Origin + Direction * Distance;

or

Code:

`x = x + cosf(angle) * speed;`
which is

Code:

`x += cosf(angle) * speed;`
• 08-22-2010
newn
This one:

Code:

```                        if(SpriteBall.GetPosition().y + SpriteBall.GetSize().y > 480.f)                         {                                 BallAngle = -BallAngle;                                 SpriteBall.SetY(480 - SpriteBall.GetSize().y - 0.1f);                         }```
i can understand why, yes, for resolution. But other two things... Not quite getting why they should break, especially paddle's size. Could you explain this a little bit further?
• 08-22-2010
VirtualAce
Code:

```if(SpriteBall.GetPosition().x < SpritePong1.GetPosition().x + SpritePong1.GetSize().x &&                           SpriteBall.GetPosition().x > SpritePong1.GetPosition().x + (SpritePong1.GetSize().x / 2.0f) &&                           SpriteBall.GetPosition().y + SpriteBall.GetSize().y >= SpritePong1.GetPosition().y &&                           SpriteBall.GetPosition().y <= SpritePong1.GetPosition().y + SpritePong1.GetSize().y)                         {                                 BallAngle = PI - BallAngle;                                 SpriteBall.SetX(SpritePong1.GetPosition().x + SpritePong1.GetSize().x + 0.1f);                         }                         if(SpriteBall.GetPosition().x + SpriteBall.GetSize().x > SpritePong2.GetPosition().x &&                           SpriteBall.GetPosition().x + SpriteBall.GetSize().x < SpritePong2.GetPosition().x + (SpritePong2.GetSize().x / 2.0f) &&                           SpriteBall.GetPosition().y + SpriteBall.GetSize().y >= SpritePong2.GetPosition().y &&                           SpriteBall.GetPosition().y <= SpritePong2.GetPosition().y + SpritePong2.GetSize().y)                         {                                 BallAngle = PI - BallAngle;                                 SpriteBall.SetX(SpritePong2.GetPosition().x - SpriteBall.GetSize().x - 0.1f);                         }```
I did not see the GetSize(). This should work for paddle size changes. But none of this code will work for ball speed changes. Your algorithm suffers from tunneling where the ball moves from point A to point B in time T but never actually collides with an object between A and B because of the time interval.

I would invite you to look at these articles/sites:
http://www.gamasutra.com/view/featur..._for_games.php
http://www.gamasutra.com/view/featur...s_collide_.php
http://www.three14.demon.nl/sweptell...tEllipsoid.pdf
http://www.realtimerendering.com/intersections.html

Moving the thread to Game Programming.
• 08-24-2010
newn
Thanks. Those are quite hard though. I never've thought, that there's so many ways of detecting collision, and every one of them requires a lot of maths knowledge, and IS hard. At least for me it is... I've not that much knowledge of mathematics, i've no resources to buy books, so learning's pretty hard too. Anyway, the good thing is, that i can do something, and i'm learning how to do, what i cannot do, hehe.

```const float PI = 3.14159f; float BallSpeed = 400.f; float BallAngle; do { BallAngle = sf::Randomizer::Random(0.f, 2 * PI); } while(std::abs(std::cos(BallAngle)) < 0.7f); float Factor = BallSpeed * App.GetFrameTime(); SpriteBall.Move(std::cos(BallAngle) * Factor, std::sin(BallAngle) * Factor);```