Allegro.cc - Online Community

Allegro.cc Forums » Game Design & Concepts » Breakout physics

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Breakout physics
Malinus
Member #11,332
September 2009

As the next step on the "learning game-dev ladder" I decided to make a breakout clone. But before I start, I could really use some few advices about the physics. Should I use vectors, which will give the ball a lot of diffrent angels? Or is this a waste of time, and I should stick to a few fixed angels (something like: 10, 45 and 70 degrees, like in DX-ball).

LennyLen
Member #5,313
December 2004
avatar

Using vectors gives you more options. You can either use a true vector, with an angle and a velocity, or just store an x and y velocity.

gnolam
Member #2,030
March 2002
avatar

LennyLen said:

You can either use a true vector, with an angle and a velocity, or just store an x and y velocity.

A vector expressed in polar (angle and length) coordinates is no more true than a vector expressed in Cartesian (grid) coordinates. :P

And yes, use vectors.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

Malinus
Member #11,332
September 2009

gnolam said:

And yes, use vectors.

Soo, it´s time to dust off my math books :P.

So the ball should bounce off at the same angel from every other surface then the paddle. Should I divide the paddle into diffrent zones where every zone represents a specific angel? Or how is it normally done? Or am I just wrong about everything?

Evert
Member #794
November 2000
avatar

Malinus said:

So the ball should bounce off at the same angel from every other surface then the paddle. Should I divide the paddle into diffrent zones where every zone represents a specific angel? Or how is it normally done? Or am I just wrong about everything?

Invert the component perpendicular to the surface of a the panel at the point of collision.
If you want to do something slightly more interesting, you could add variations on that instead, but that is the gist of it.

Malinus
Member #11,332
September 2009

Evert said:

Invert the component perpendicular to the surface of a the panel at the point of collision.
If you want to do something slightly more interesting, you could add variations on that instead, but that is the gist of it.

Yup that part i understand (just like light). But what when the ball hits the paddle?

OnlineCop
Member #7,919
October 2006
avatar

Malinus said:

Should I divide the paddle into diffrent zones where every zone represents a specific angel?

Yes. It makes the game a LOT more fun. Having a bland "always 45-degree" (or whatever angle) bounce makes the ball "landing" location very predictable (even with the tiles themselves bouncing the ball back).

Start your angle off in a range between 30 and 60 degrees in one of the four quadrants (so one of: 30..60, 120..150, 210..240, 300..330).

Your 'x' coordinate is calculated with cos(angle) and your 'y' is sin(angle). Even while the angle changes, the total velocity of the ball remains the same, so even if it shoots off to the side from hitting the corner of the paddle, it will still be traveling at the same speed.

More often than not, the moving ball (because of its velocity) will travel further than a wall's, brick's, or paddle's [closest] outside edge. To deal with that, and make it bounce correctly, calculate the time where the ball just touches the edge of that object, then backtrack the ball to that position. Reverse the ball's perpendicular direction (so it bounces off the object), then move the ball forward (in that new direction) by the amount you "backtracked" earlier. So even at high speeds, your ball will calculate the correct position to bounce at.

Michael Faerber
Member #4,800
July 2004
avatar

You could also just give the ball a different direction when the paddle moves upon collision.

For example, you move the paddle to the right and the ball is approaching, it will be reflected to the right.

--
"The basic of informatics is Microsoft Office." - An informatics teacher in our school
"Do you know Linux?" "Linux? Isn't that something for visually impaired people?"

Malinus
Member #11,332
September 2009

OnlineCop said:

Yes. It makes the game a LOT more fun. Having a bland "always 45-degree" (or whatever angle) bounce makes the ball "landing" location very predictable (even with the tiles themselves bouncing the ball back).

Start your angle off in a range between 30 and 60 degrees in one of the four quadrants (so one of: 30..60, 120..150, 210..240, 300..330).

Your 'x' coordinate is calculated with cos(angle) and your 'y' is sin(angle). Even while the angle changes, the total velocity of the ball remains the same, so even if it shoots off to the side from hitting the corner of the paddle, it will still be traveling at the same speed.

More often than not, the moving ball (because of its velocity) will travel further than a wall's, brick's, or paddle's [closest] outside edge. To deal with that, and make it bounce correctly, calculate the time where the ball just touches the edge of that object, then backtrack the ball to that position. Reverse the ball's perpendicular direction (so it bounces off the object), then move the ball forward (in that new direction) by the amount you "backtracked" earlier. So even at high speeds, your ball will calculate the correct position to bounce at.

Now this was helpfull.
So it´s basicly just

#SelectExpand
1x+=cos(angel / 180 * PI); 2y+=sin(angel / 180 * PI);

And then when it collides with the paddle I just change angle (according to where on the paddle it hits).

Reversing the ball of objects should be something like:
angel=((-cos(angel / 180 * PI))*180)/PI;

But in the part about backtracking you really lost me. I got the point but i really don´t know how it should be done. Or more precisely: how to calculate the time where the ball just touches the edge of the object? Especially when i think the ball´s velocity will be controlled by a timer.

gnolam
Member #2,030
March 2002
avatar

No. Use Cartesian vectors. Then, as Evert said, you can just invert the component perpendicular to the surface hit.

// Initial velocity
float xv = cos(some_angle);
float yv = sin(some_angle);

void Update()
{
    x += xv;
    y += yv;
}

void ReflectOffVerticalSurface()
{
    xv = -xv;
}
// Reflection off a horizontal surface is left as an exercise to the reader ;)

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

Malinus
Member #11,332
September 2009

gnolam said:

No. Use Cartesian vectors. Then, as Evert said, you can just invert the component perpendicular to the surface hit.

But since the sin & con use radians i still need to convert the angel to radians, right? Or am I just wrong about everything?:P

All the back backtracking talk OnlineCop did, made me a little dizzy. Won´t it work with just something like:

#SelectExpand
1if(x >= (SCREEN_W - ball->w) ){ 2xv = -xv; 3}

etc. etc.
Or isn´t it accurate enough at high velocity?

But my real question now is, how do I add velocity? I tried just adding a xspeed and yspeed to the x,y and invert it when needed. But it still seam to affect the angel as well.

LennyLen
Member #5,313
December 2004
avatar

For future reference this is an angel:

{"name":"angel4c.gif","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/1\/419deb088cca25005eb568582c1f1dd3.gif","w":600,"h":419,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/1\/419deb088cca25005eb568582c1f1dd3"}angel4c.gif

This is an angle:

{"name":"800px-Angle_measure.svg.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/d\/2da9ead9838239217018f36443b2cbd2.png","w":800,"h":563,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/d\/2da9ead9838239217018f36443b2cbd2"}800px-Angle_measure.svg.png

Malinus said:

All the back backtracking talk OnlineCop did, made me a little dizzy. Won´t it work with just something like...Or isn´t it accurate enough at high velocity?

That will work, but if the ball goes sufficiently outside the wall, you may have a few frames where it isn't visible.

Malinus
Member #11,332
September 2009

Well i should have paid more attention at my english class´ :P. But how to add velocity without affecting the angle?

EDIT: and at my math class as well :P

gnolam
Member #2,030
March 2002
avatar

Malinus said:

But my real question now is, how do I add velocity? I tried just adding a xspeed and yspeed to the x,y and invert it when needed. But it still seam to affect the angel as well.

Multiply both velocity components by the same value.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

verthex
Member #11,340
September 2009
avatar

You take each component of the vectors you wanna add and then you find the magnitude just as

gnolam said:

Multiply both velocity components by the same value.

heres a tutorial on vectors ;D

OnlineCop
Member #7,919
October 2006
avatar

Malinus said:
x+=cos(angel / 180 * PI);
y+=sin(angel / 180 * PI);

Malinus said:

But my real question now is, how do I add velocity?

Your equation assumes that your angle is stored as a degree, and not a radian. If you started out with the angle as a radian, you can simplify your math (it speeds up your calculation, because you don't have to re-calculate "angle / 180 * PI" every time). Instead, set your initial angle to be in radians, and you'll be set:

   static const DEG2RAD = (double)M_PI / (double)180.0;

   // quadrant 0 is top-right, 1 is top-left, 2 is bottom-left, 3 is bottom-right
   unsigned char quadrant = rand % 4;

   // rand_twosided() returns a random value between 30..60 degrees
   double angle = rand_twosided(45.0, 1.0/3.0) * DEG2RAD + M_PI/2.0 * quadrant;

To figure out the velocity, pass in the DELTA time (from your last logic update):

void update_ball(double delta_time)
{
   x += (velocity * delta_time) * cos(angle);
   y += (velocity * delta_time) * sin(angle);
   // ... other stuff ...
}

I'm in class now, so when I have more time, I'll try to reply about how to find the "backtrack amount". ;D

Malinus
Member #11,332
September 2009

After reading your explanation, looking at my old math books (ahh not THAT old), and reading some tutorials online I think I got the hang of it now. So thanks for the explanations guys.

And OnlineCop if you get time I would really appreciate it. But don´t let it distract you from class, or you will end like me :P. Hehe I´m just happy I haven´t started a 3D project yet ;D.

gnolam
Member #2,030
March 2002
avatar

Argh. Polar coordinates are not the tool for the job here. They just complicate things.

Also,

OnlineCop said:

x += (velocity * delta_time) * cos(angle);

You mean speed. Velocity is a vector quantity, speed is a scalar.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

OnlineCop
Member #7,919
October 2006
avatar

gnolam said:

You mean speed. Velocity is a vector quantity, speed is a scalar.

You're probably right. I meant speed. Saying "velocity" just sounds like you're so much smarter than your average "speed" user.

I'm still looking for some good examples of backtracking explained better than I can do (I've tried writing some code snippets and examples, but they fail).

You can always try this wiki for some help; I haven't looked through it extensively enough to see whether it discusses this, but it's worth a shot.

Malinus
Member #11,332
September 2009

So after looking at the internet and reading about the backtracking algorithm, which is almost the same as the brute-force algorithm, I assume you are not referring to that algorithm. So instead I tried with making a function that looks something like:

int trace(){

int tracing=0;
for(int a=0;a<100;a++){
   x += xv*speed;
   y += yv*speed;
   tracing++;

   if(collision)
   return tracing;
    }

return 0;
}

And run it every logic, to make it simulate that the logics of ball moving happend 100 times. And return after how many logics the collision will happen.

But I still can´t see any advantage, because I still use bounding box collision detection, for collisions :s... So it´s just a lot of extra work for the CPU.

If I have to be honest I think I´m pretty much off.

OnlineCop
Member #7,919
October 2006
avatar

To be honest, I've been too busy to respond. Sorry.

I've usually used this as a good starting point, since it helps with several different shapes that collide with each other. Some of the code (near the bottom) also use timer calculations to determine the "right" time, when the collisions first occur. It may be helpful.

EDIT: So may this PDF.

Malinus
Member #11,332
September 2009

OnlineCop said:

To be honest, I've been too busy to respond. Sorry.

Wow, dont worry about that. Im just really happy for the help.

OnlineCop said:

I've usually used this[www.gamedev.net] as a good starting point, since it helps with several different shapes that collide with each other. Some of the code (near the bottom) also use timer calculations to determine the "right" time, when the collisions first occur. It may be helpful.

EDIT: So may this[www.peroxide.dk] PDF.

Well even though Im thankfull for the reading, Im not really sure how much effort I should put into making a ball consisting of 10 pixels collide perfect. But I guess I should still try, becouse even though a simple bounding box collision detection will be more then enough for a simple game like breakout, I will be able to use the stuff I learn in further projects.

OnlineCop
Member #7,919
October 2006
avatar

A quick-and-dirty that you can do is simply backtracking completely, and reverse direction from that point (basically, the last location BEFORE your ball moved from the current update() call.

So let's say that your ball goes too far horizontally. Since you had calculated the "current" position like this:

   x += (delta_time * velocity) * cos(angle);

then to backtrack, simply undo that operation (one of two ways):

   x -= (delta_time * velocity) * cos(angle);

...or...

   old_x = x;
   x += (delta_time * velocity) * cos(angle);

   if ( /* collision test */ == true)
   {
      angle = M_PI - angle;
      x = old_x + (delta_time * velocity) * cos(angle);
   }

This way, it's not terribly accurate, but the math is a lot simpler, and at high framerates, you'll never even know that it was "imprecise calculations" (you'll see it if your framerate drops and your ball suddenly ricochets off of apparently "nothing").

One other problem with Breakout clones is that you often try to do your collision detection against ALL of the bricks on the screen, every frame. The best thing to do for that is to optimize your collision check, since that's probably one of the bigger issues you'll deal with.

Imagine testing against every tile when you only have about 20 tiles on-screen. Not a big deal, even with a "check against every single tile"-unoptimized collision check. But get to a level that's nothing but tiles (100-200 tiles), and that same collision-check algorithm could make your game come to a screeching halt. But that's a different thread... ::)

Schyfis
Member #9,752
May 2008
avatar

Quote:

int tracing=0;
for(int a=0;a<100;a++){
   ...
   tracing++;
   ...
}

Just a heads-up that a and tracing will always be the same number. You can get rid of tracing and return a.

________________________________________________________________________________________________________
[freedwill.us]
[unTied Games]

Malinus
Member #11,332
September 2009

Schyfis said:

Quote:

int tracing=0;
for(int a=0;a<100;a++){
...
tracing++;
...
}

Just a heads-up that a and tracing will always be the same number. You can get rid of tracing and return a.

I must say I´m more stupid then i thought....

OnlineCop said:

then to backtrack, simply undo that operation (one of two ways):

x -= (delta_time * velocity) * cos(angle);

You can´t imagine how helpfull it was. I finally (/about time!!) understand. How could i possibly be so slow? I rally need to start my study now... hehe

OnlineCop said:

One other problem with Breakout clones is that you often try to do your collision detection against ALL of the bricks on the screen, every frame. The best thing to do for that is to optimize your collision check, since that's probably one of the bigger issues you'll deal with.

Imagine testing against every tile when you only have about 20 tiles on-screen. Not a big deal, even with a "check against every single tile"-unoptimized collision check. But get to a level that's nothing but tiles (100-200 tiles), and that same collision-check algorithm could make your game come to a screeching halt. But that's a different thread...

I actually allready considered that. I think I will only check collision with the titles that have less then 4 neighbours, even though it may not be the best optimization (heh), I think it will be enough....

 1   2 


Go to: