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.

How can I implement gravity? Not for a particular language, just pseudocode...

share|improve this question
1  
2  
The accepted answer on this question should help you: gamedev.stackexchange.com/questions/13178/… –  Tetrad Aug 8 '11 at 15:47

5 Answers 5

up vote 21 down vote accepted

As others have noted in the comments, the basic Euler integration method described in tenpn's answer suffers from a few problems:

  • Even for simple motion, like ballistic jumping under constant gravity, it introduces a systematic error.

  • The error depends on the timestep, meaning that changing the timestep changes object trajectories in a systematic way that may be noticed by players if the game uses a variable timestep. Even for games with a fixed physics timestep, changing the timestep during development can noticeably affect the game physics such as the distance that an object launched with a given force will fly, potentially breaking previously designed levels.

  • It doesn't conserve energy, even if the underlying physics should. In particular, objects that should oscillate steadily (e.g. pendulums, springs, orbiting planets, etc.) may steadily accumulate energy until the whole system blows apart.

Fortunately, it's not hard to replace Euler integration with something that is almost as simple, yet has none of these problems — specifically, a second-order symplectic integrator such as leapfrog integration or the closely related velocity Verlet method. In particular, where basic Euler integration updates the velocity and position as:

acceleration = force(time, position) / mass;
time += timestep;
position += timestep * velocity;
velocity += timestep * acceleration;

the velocity Verlet method does it like this:

acceleration = force(time, position) / mass;
time += timestep;
position += timestep * (velocity + timestep * acceleration / 2);
newAcceleration = force(time, position) / mass;
velocity += timestep * (acceleration + newAcceleration) / 2;

If you have multiple interacting objects, you should update all their positions before recalculating the forces and updating the velocities. The new acceleration(s) can then be saved and used to update the position(s) on the next timestep, reducing the number of calls to force() down to one (per object) per timestep, just like with the Euler method.

Also, if the acceleration is normally constant (like gravity during ballistic jumping), we can simplify the above to just:

time += timestep;
position += timestep * (velocity + timestep * acceleration / 2);
velocity += timestep * acceleration;

where the extra term in bold is the only change compared to basic Euler integration.

Compared to Euler integration, the velocity Verlet and leapfrog methods have several nice properties:

  • For constant acceleration, they give exact results (up to floating point roundoff errors, anyway), meaning that ballistic jump trajectories stay the same even if the timestep is changed.

  • They are second order integrators, meaning that, even with varying acceleration, the average integration error is only proportional to the square of the timestep. This can allow for larger timesteps without compromising accuracy.

  • They are symplectic, meaning that they conserve energy if the underlying physics do (at least as long as the timestep is constant). In particular, this means that you won't get things like planets spontaneously flying out of their orbits, or objects attached to each other with springs gradually wobbling more and more until the whole thing blows up.

Yet the velocity Verlet / leapfrog method are nearly as simple and fast as basic Euler integration, and certainly much simpler than alternatives like fourth-order Runge-Kutta integration (which, while generally a very nice integrator, lacks the symplectic property and requires four evaluations of the force() function per time step). Thus, I would strongly recommend them for anyone writing any sort of game physics code, even if it's as simple as jumping from one platform to another.


Edit: While the formal derivation of the velocity Verlet method is only valid when the forces are independent of the velocity, in practice you can use it just fine even with velocity-dependent forces such as fluid drag. For best results, you should use the initial acceleration value to estimate the new velocity for the second call to force(), like this:

acceleration = force(time, position, velocity) / mass;
time += timestep;
position += timestep * (velocity + timestep * acceleration / 2);
velocity += timestep * acceleration;
newAcceleration = force(time, position, velocity) / mass;
velocity += timestep * (newAcceleration - acceleration) / 2;

I'm not sure if this particular variant of the velocity Verlet method has a specific name, but I've tested it and it seems to work very well. It's not quite as accurate as fouth-order Runge-Kutta (as one would expect from a second-order method), but it's much better than Euler or naïve velocity Verlet without the intermediate velocity estimate, and it still retains the symplectic property of normal velocity Verlet for conservative, non-velocity-dependent forces.

Edit 2: A very similar algorithm is described e.g. by Groot & Warren (J. Chem. Phys. 1997), although, reading between the lines, it seems that they sacrificed some accuracy for extra speed by saving the newAcceleration value computed using the estimated velocity and reusing it as the acceleration for the next timestep. They also introduce a parameter 0 ≤ λ ≤ 1 which is multiplied with acceleration in the initial velocity estimate; for some reason, they recommend λ = 0.5, even though all my tests suggest that λ = 1 (which is effectively what I use above) works as well or better, with or without the acceleration reuse. Maybe it's got something to do with the fact that their forces include a stochastic Brownian motion component.

share|improve this answer
    
Velocity Verlet it's nice but it cannot have potential dependant by velocity, so the friction can't be implemented. I think that Runge-Kutta 2 is the best for my purpose ;) –  Pizzirani Leonardo Nov 1 '12 at 14:30
1  
@PizziraniLeonardo: You can use (a variant of) velocity Verlet just fine even for velocity-dependent forces; see my edit above. –  Ilmari Karonen Nov 1 '12 at 21:55
1  
Literature does not give this interpretation of Velocity Verlet a different name. It relies on a predictor-corrector strategy, as also stated in this paper fire.nist.gov/bfrlpubs/build99/PDF/b99014.pdf . –  teodron Nov 2 '12 at 15:13
    
@teodron: Cool, thanks for the reference. The paper you linked to cites an earlier paper, which I've now added to my answer. –  Ilmari Karonen Nov 2 '12 at 16:54
1  
@Unit978: That depends on the game, and specifically on the physics model it implement. The force(time, position, velocity) in my answer above is just shorthand for "the force acting on an object at position moving at velocity at time". Typically, the force would depend on things like whether the object is in freefall or sitting on a solid surface, whether any other nearby objects are exerting a force on it, how fast it's moving over a surface (friction) and/or through a liquid or gas (drag), etc. –  Ilmari Karonen 22 hours ago

Every update loop of your game, do this:

if (collidingBelow())
    gravity = 0;
else gravity = [insert gravity value here];

velocity.y += gravity;

For instance, in a platformer, once you jump gravity would be enabled (collidingBelow tells you whether or not there is ground right below you) and once you hit the ground it would be disabled.

Besides this, to implement jumps, then do this:

if (pressingJumpButton() && collidingBelow())
    velocity.y = [insert jump speed here]; // the jump speed should be negative

And pretty obviously, in the update loop you also have to update your position:

position += velocity;
share|improve this answer
5  
What do you mean? Just pick your own gravity value and since it changes your velocity, not just your position, it looks natural. –  Pecant Aug 9 '11 at 12:37
1  
I dislike turning off gravity ever. I think that gravity should be constant. The thing that should change (imho) is your ability to jump. –  ultifinitus Aug 26 '11 at 15:20
1  
If it helps, think of it as 'falling' rather than actually 'gravity'. The function as a whole controls whether or not the object is falling due to gravity. Gravity itself exists just as that [insert gravity value here]. So in that sense, gravity is constant, you just don't use it for anything unless the object is airborne. –  Jason Pineo Aug 26 '11 at 16:01
1  
This code is frame-rate dependent, which isn't great, but if you have a constant update then you're laughing. –  tenpn Aug 26 '11 at 16:09
1  
-1, sorry. Adding velocity and gravity, or position and velocity, that just does not make sense. I understand the shortcut you're doing, but it's wrong. I would hit any student or trainee or colleague doing that with the largest cluebat I could find. Consistency of units does matter. –  Sam Hocevar Nov 2 '12 at 0:52

A proper frame-rate independent* newtonian physics integration:

Vector forces = 0.0f;

// gravity
forces += down * m_gravityConstant; // 9.8m/s/s on earth

// left/right movement
forces += right * m_movementConstant * controlInput; // where input is scaled -1..1

// add other forces in for taste - usual suspects include air resistence
// proportional to the square of velocity, against the direction of movement. 
// this has the effect of capping max speed.

Vector acceleration = forces / m_massConstant; 
m_velocity += acceleration * timeStep;
m_position += velocity * timeStep;

Tweak gravityConstant, movementConstant and massConstant until it feels right. It is an intuitive thing and can take a while to get feeling great.

It's easy to extend the forces vector to add new gameplay - for instance add a force away from any nearby explosion, or towards black holes.

*edit: these results will be wrong over time, but may be "good enough" for your fidelity or aptitude. See this link http://lol.zoy.org/blog/2011/12/14/understanding-motion-in-games for more info.

share|improve this answer
3  
Don't use Euler integration. See this article by Glenn Fiedler which explains the problems and solutions better than I could. :) –  Martin Sojka Aug 26 '11 at 16:18
1  
I understand how Euler is inaccurate over time, but I think there are scenarios where it doesn't really matter. As long as the rules are consistent for everyone, and it "feels" right, it's fine. And if you're just learning about phyiscs, it's very easy to remember and implmenet. –  tenpn Aug 26 '11 at 16:28
    
...good link though. ;) –  tenpn Aug 26 '11 at 16:35
3  
You can fix most of the issues with Euler integration simply by replacing position += velocity * timestep above with position += (velocity - acceleration * timestep / 2) * timestep (where velocity - acceleration * timestep / 2 is simply the average of the old and new velocities). In particular, this integrator gives exact results if acceleration is constant, as it typically is for gravity. For better accuracy under varying acceleration, you can add a similar correction to the velocity update to get velocity Verlet integration. –  Ilmari Karonen Oct 31 '12 at 12:55
    
Your arguments make sense, and the inaccuracy is often not a big deal. But you should not claim it is a “proper frame-rate independent” integration, because it just isn’t (framerate independent). –  Sam Hocevar Nov 2 '12 at 0:48

If you want to implement gravity on a slightly bigger scale, you can use this kind of calculation each loop:

for each object in the scene
  for each other_object in the scene not equal to object
    if object.mass * other_object.mass / object.distanceSquaredBetweenCenterOfMasses(other_object) < epsilon
      abort the calculation for this pair
    if object.mass is much, much bigger than other_object.mass
      abort the calculation for this pair
    force = gravitational_constant
            * object.mass * other_object.mass
            / object.distanceSquaredBetweenCenterOfMasses(other_object)
    object.addForceAtCenterOfMass(force * object.normalizedDirectionalVectorTo(other_object))
  end for loop
end for loop

For even bigger (galactic) scales, gravity alone won't suffice to create "real" motion though. The interaction of star systems is to a significant and very visible extent dictated by Navier-Stokes equations for fluid dynamics, and you'll have to keep the finite speed of light - and thus, gravity - in mind too.

share|improve this answer

Pecant's answser ignored frame time, and that makes your physics behavior differently from time to time.

If you are going to make a very simple game, you can make your own little physics engine -- assign mass and all kinds of physics parameters for every moving object, and do collision detection, then update their position and velocity every frame. In order to accelerate this progress, you need to simplify the collision mesh, reduce calls of collision detection, etc. In most cases, that's a pain.

It's better to use physics engine like physix, ODE and bullet. Any of them will be stable and efficient enough for you.

http://www.nvidia.com/object/physx_new.html

http://bulletphysics.org/wordpress/

share|improve this answer
3  
-1 Unhelpful response that does not answer the question. –  doppelgreener Aug 10 '11 at 7:39
3  
well, if you want to adjust it for time, you can just scale the velocity by the elapsed time from the last update(). –  Pecant Aug 14 '11 at 1:55

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.