How can I implement gravity? Not for a particular language, just pseudocode...
|
|
As others have noted in the comments, the basic Euler integration method described in tenpn's answer suffers from a few problems:
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 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:
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 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 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 |
|||||||||||
|
|
Every update loop of your game, do this:
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:
And pretty obviously, in the update loop you also have to update your position:
|
|||||||||||||||||||||
|
|
A proper frame-rate independent* newtonian physics integration:
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. |
|||||||||||||||
|
|
If you want to implement gravity on a slightly bigger scale, you can use this kind of calculation each 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. |
|||
|
|
|
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. |
|||||||||
|