Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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?

share|improve this question
    
When you say the vertical velocities "slowly decay", do you mean that they fall downward or that the velocity decreases with time, or what? –  Olhovsky Jun 5 '11 at 4:13
    
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.) –  Olhovsky Jun 5 '11 at 4:15
    
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. –  Olhovsky Jun 5 '11 at 4:17
    
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 –  loneboat Jun 5 '11 at 4:18
    
I don't understand what you mean by "continue to press against a wall"?? –  loneboat Jun 5 '11 at 4:21
show 9 more comments

3 Answers

up vote 9 down vote accepted

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.

share|improve this answer
    
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 –  Olhovsky Jun 5 '11 at 19:12
    
+1, using your integration into position, that seems to work out with constant accelleration and constant timestep. –  Olhovsky Jun 5 '11 at 21:10
    
@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? –  loneboat Jun 5 '11 at 21:16
    
@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 –  Maik Semder Jun 5 '11 at 21:47
    
@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 –  Maik Semder Jun 6 '11 at 11:33
show 3 more comments

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...

share|improve this answer
    
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. –  loneboat Jun 5 '11 at 4:32
    
You are using Euler integration over a finite timestep. It's not that accurate. –  Olhovsky Jun 5 '11 at 4:33
    
I will elaborate, one moment. –  Olhovsky Jun 5 '11 at 4:33
    
Reading this now (found it by the keywords you mentioned) : stackoverflow.com/questions/2769466/… –  loneboat Jun 5 '11 at 4:39
    
I started writing a detailed explanation, but I decided to give you a link instead. –  Olhovsky Jun 5 '11 at 4:40
show 21 more comments

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

share|improve this answer
    
+1, I think you're right. –  Olhovsky Jun 5 '11 at 19:08
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.