5
\$\begingroup\$

Programming in Java. Tinkering around with physics. My entities all have position and velocity. In the main loop, all I'm doing is applying gravity and bouncing off the edges, like so:

    //  add gravity vector
    o.velocity.add(GRAVITY.cpy().mul(dt));

    //  bounce off walls
    if ((o.position.x<0 && o.velocity.x<0) || (o.position.x>WORLD_SIZE_X && o.velocity.x>0))
        o.velocity.x*=-1;

    //  bounce off of ground
    if (o.position.y<=0.0f) {
        o.position.y=0.0f;
        if (o.velocity.y<0)
            o.velocity.y *= -1;
    }

The x and y values of my vectors are just floats.

For the first second it looks like it's working fine, but the vertical velocities slowly decay. Any idea why?

\$\endgroup\$
14
  • \$\begingroup\$ When you say the vertical velocities "slowly decay", do you mean that they fall downward or that the velocity decreases with time, or what? \$\endgroup\$
    – Olhovsky
    Jun 5, 2011 at 4:13
  • \$\begingroup\$ GRAVITY.cpy().mul(dt) is just multiplying time by the gravity vector and adding it to the velocity vector, right? Are you sure that's what it's doing? (That's a weird way of writing z.velocity += Gravity * dt;, for Java code.) \$\endgroup\$
    – Olhovsky
    Jun 5, 2011 at 4:15
  • \$\begingroup\$ By the way, is it your intention to allow the velocity to continue to press against a wall? If not, you should be flipping velocity in the same way that you do when you bounce off the ground. \$\endgroup\$
    – Olhovsky
    Jun 5, 2011 at 4:17
  • \$\begingroup\$ By decay I mean it bounces just like a real ball, eventually stopping bouncing. It's actually a nice effect, but unintended so it's bothering me! :-) The reason I'm writing GRAVITY.cpy().mul(dt) is because I'm using simple 2d vector objects with adding/multiplying built in, so I can't just do v1 = v1 + v2 \$\endgroup\$
    – loneboat
    Jun 5, 2011 at 4:18
  • \$\begingroup\$ I don't understand what you mean by "continue to press against a wall"?? \$\endgroup\$
    – loneboat
    Jun 5, 2011 at 4:21

3 Answers 3

8
\$\begingroup\$

As long as you only apply constant acceleration (i.e. from constant gravity) Eulers Method is accurate and the ball must bounce forever, reaching its initial position again after each bounce phase. If not, then there is something wrong with the implementation of Euler's Method. Here is how it should look like:

void update(float dt)
{
    position += velocity * dt + acceleration * 0.5 * dt * dt;
    velocity += acceleration * dt;
    // handling only the simple ground collision case here
    if(position.x < radius)
    {
        velocity = -velocity;
    }        
}

Note the acceleration is constant here, its simply the gravity.

EDIT:

It seems both, the article on gaffergames and the code in the question use a simpler form of Euler's Method, namely:

     position += velocity * dt;
     velocity += acceleration * dt;

whereas this one as also shown in this paper:

     position += velocity * dt + acceleration * 0.5 * dt * dt;
     velocity += acceleration * dt;

is still capable of correctly integratiing constant accelerations.

Note: This answer is not supposed to mean that the Euler Method is a good choice for complex physics and non-constant accelerations, nor that you should stick to it once you want to add more physics dynamics to your scene. However, if the application will only use constant acceleration, then this method perfectly fits your needs.

\$\endgroup\$
8
  • \$\begingroup\$ I don't think that it's accurate for constant accelleration. Read the link I gave in my answer: gafferongames.com/game-physics/integration-basics \$\endgroup\$
    – Olhovsky
    Jun 5, 2011 at 19:12
  • \$\begingroup\$ +1, using your integration into position, that seems to work out with constant accelleration and constant timestep. \$\endgroup\$
    – Olhovsky
    Jun 5, 2011 at 21:10
  • \$\begingroup\$ @Olhovsky: I'm still confused. From the article: "Euler integration is the most basic of numerical integration techniques. It is only 100% accurate if the rate of change is constant over the timestep." Isn't my rate of change here constant, since I never change my gravity? \$\endgroup\$
    – loneboat
    Jun 5, 2011 at 21:16
  • \$\begingroup\$ @loneboat yes, the rate of change of the velocity, but not the rate of change of the position, as he explains in the next sentence \$\endgroup\$ Jun 5, 2011 at 21:47
  • \$\begingroup\$ @loneboat @Olhovsky this paper also says the correct Euler Method implementation is pos(t+dt) = pos(t) + dt*v(t) + 0.5*dt*dt*a(t) and not just `pos(t+dt) = pos(t) + dt*v(t)' which basically says the gaffa side and you used the wrong Euler Method, which at least is correct for constant acceleration \$\endgroup\$ Jun 6, 2011 at 11:33
5
\$\begingroup\$

Your objects are bouncing with subsequently smaller bounces because you are applying basic newtonian physics rules to your objects, so they mimic behavior of such objects as you'd expect them to in real life.

You are constantly applying gravity to the velocity of the objects.

When you flip the direction of velocity, the object is now moving up, with an upward velocity, but you are removing some of this velocity with a downward gravity velocity application. With perfect elasticity, and zero friction, you'd expect the object to reach the previous height, but...

You are using Euler integration to approximate the integration of force. This approximation underestimates the effect of the force application.

So when your object hits the ground and velocity is flipped, it can't reach as high as it was before, because the application of gravity is not perfectly accurately integrated (it would be if you had an infintesimally small timestep).

Read "Why Euler's is never good enough": http://gafferongames.com/game-physics/integration-basics/

I think that Euler's actually is often good enough, but that's another matter...

\$\endgroup\$
26
  • \$\begingroup\$ Hmmm, but even with Newtonian physics, there isn't any explicit decay in motion. If a rubber ball were to bounce with perfect efficiency (nothing lost to heat or rotation), wouldn't it bounce forever? Since I'm just flipping the vector, I would expect it to be a "perfect" bounce, and it should bounce all the way back up to its initial height before dropping again. \$\endgroup\$
    – loneboat
    Jun 5, 2011 at 4:32
  • \$\begingroup\$ You are using Euler integration over a finite timestep. It's not that accurate. \$\endgroup\$
    – Olhovsky
    Jun 5, 2011 at 4:33
  • \$\begingroup\$ I will elaborate, one moment. \$\endgroup\$
    – Olhovsky
    Jun 5, 2011 at 4:33
  • \$\begingroup\$ Reading this now (found it by the keywords you mentioned) : stackoverflow.com/questions/2769466/… \$\endgroup\$
    – loneboat
    Jun 5, 2011 at 4:39
  • \$\begingroup\$ I started writing a detailed explanation, but I decided to give you a link instead. \$\endgroup\$
    – Olhovsky
    Jun 5, 2011 at 4:40
2
\$\begingroup\$

Olhovsky explains the problem, but he left out the simple fix. Apply gravity twice.

Basically you are doing three things over and over.

Gravity
Collision
Movement

Swap the order of any two and you'd actually get the opposite problem. Do a halfway swap and you are even. In practice that means do half the gravity before collision checks, and half the gravity after.

½ Gravity
Collision
½ Gravity
Movement

\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .