Gravity. How??

Ok so I was reminiscing on my times of my high school programming class. This classed darkBASIC to create some simple 3D games rather easily. Anyway, I could never figure out to make gravity work on this game. I could move around, I could move up and down, but I tried to make a jumping system work but I just could never get it. I could never think of a way to simulate gravity in this program. And now, I am just curious as to how people do it. It seems to be a common thing in every video game now. Not to mention various simulation.

So I guess I'm looking for a discussion on gravity simulation on a computer. Algorithms, code samples, theory, etc. Let's make this interesting!
Assuming your movement works by calculating deltas (from user input, collisions and physics) to be applied to the player position, gravity and jumping are rather simple. They are merely deltas that get applied to the players main delta.

Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//assume that a positive y value translates to down

struct Vector3d
{
    float x, y, z;

    Vector3d(float _x, float _y, float _z);
    //add basic operators
};

//these values are made up, you should probably use more realistic ones...
const Vector3d Gravity(0, 0.9, 0);
const Vector3d Drag(0.9, 0.9, 0.9); //values should be added/subtracted from player deltas to make them closer to 0
const Vector3d Jump(0, -5, 0);

const Vector3d PlayerDelta, PlayerPosition;

//in your physics function
if (Input(JumpKey))
PlayerDelta += Jump;
//other keys

//do collisions

PlayerDelta.Zero(Drag); //see above comment by Drag
PlayerDelta += Gravity;
PlayerPosition += PlayerDelta;
Last edited on
I have not been exposed to deltas yet. Could you give a quick explanation as to what it is and how it applies here?
A "delta" is just the small change that is, in this case, occurring in your position. For example, when you are walking forward, you are adjusting the position to be slightly forward from where you were as you move. Those small adjustments are your "deltas".
Oooh I have seen those actually. Just weird hearing it in this context. Ok, so what exactly are these functions doing then? I don't get how it knows when to stop going up and start going down in a natural way. I'd imagine moving in a parabolic way would be best, but I don't see how it gets implemented
The idea is that you have a delta vector (in this case PlayerDelta) indicating what direction the player currently is moving. For example, if you are moving in the x-direction you might have a PlayerDelta of <2, 0, 0> or something.

To add gravity, all you need to do is add some y-direction vector (positive, in the case of the code above) after you've finished calculating your PlayerDelta to pull them towards the ground.

In the code above, you have the PlayerDelta being calculated up until line 26. There, PlayerDelta is how you would want the player to move without including any gravity. Line 26 itself adjusts the movement to have gravity try to pull the player down slightly. That's all.
PlayerDelta is a long way to say "speed".

As for alternatives, I'm currently working on something that would use pre-calculated parabolas. Although that too only works for boring flat gravity. In general, it is a very complex task. See http://en.wikipedia.org/wiki/Three-body_problem
Ok so a player vector just holds 3 elements, speed in the <x,y,z> directions? And you just apply this to something...? Sorry I feel very dumb in this field. I havent had a physics class in a good 3 years.

And to clarify, vectors in this sense are different than std::vector?
Ok so a player vector just holds 3 elements, speed in the <x,y,z> directions? And you just apply this to something...?

Yes, that's right. That delta would be the change in position.

And to clarify, vectors in this sense are different than std::vector?

Correct. It is a physics/mathematical vector; in this case, you might call it a "vector in Euclidean 3-space".
http://en.wikipedia.org/wiki/Euclidean_vector
Ok cool, yea I actually just read up a bit of the wiki page on it. Though, it says a Euclidean vector is for moving in one direction? What if we're moving in all three directions? Or even 2 directions like jumping?
velocity is a product of change in position with respect to time:

v = (x2 - x1) / (t2 - t1)

And acceleration is a product of the change in velocity with respect to time:

a = (v2 - v1) / (t2 - t1)

You can apply a linear velocity to a unit vector in the normal way:

vector * scalar

And linear velocity in 2-3D can be found by:

vel = sqrt( (x_vel * x_vel) + (y_vel * y_vel) + (z_vel * z_vel))

If you're wanting to track position in 2-3D independently, you'll need to know acceleration, starting velocity and starting position:

x2 = 1/2 * a_x * (tf - ti)^2 + xvi * (tf - ti) + xi

where xi is starting x position, a_x is acceleration in x direction, xvi is the initial x velocity, ti is start or initial time, tf is final time.

Also, the SI value for gravity is 9.81m/(s * s).

So for y (2 and 3D standard axis for elevation)

y2 = 1/2 * -9.81 * (tf - ti)^2 + yvi * (tf - ti) + yi

(I prefer -y being down because that is how all my main modeler works).

Barring the escape velocity threshold, any object traveling up will eventually come back down as t increases. However, escape velocity only applies if gravity decreases with distance from source and should follow the inverse square law, as in Newton's Law of Universal Gravitation(assuming you're not modeling relativistic physics):

http://en.wikipedia.org/wiki/Newton%27s_law_of_universal_gravitation


I used this site to get a good explaination of the runge-kutta integration method:

http://gafferongames.com/game-physics/

Most physics engines use the Euler integrator, but it's not as accurate as the runge-kutta. Newton (http://newtondynamics.com/forum/newton.php) uses Euler and it so failed the integration test, it had to get its own scale of fail. However, it shines when it comes to friction.

Check out:

http://en.wikibooks.org/wiki/Main_Page

There is a reasonable online physics text available:

http://en.wikibooks.org/wiki/Modern_Physics

You'll want mechanics.

http://en.wikibooks.org/wiki/Mechanics




Last edited on
ResidentBiscuit wrote:
I havent had a physics class in a good 3 years.


I haven't had any physics classes yet, I just Google and play around with my code to figure stuff out.

@roberts: +1
So it seems as if simulating physics in a computer system can be kind of a challenge. Looks like I have some research and testing to do for awhile now haha
Oh yeah, it's taking me a while to make a program the calculates volume (from which I can calculate density), center of mass, moments of inertia and center of percussion.

I'm almost done with the spanner. The rest will be cake after that, I hope.

One other little factoid:

Taking the derivative of the position equation:

y2 = 1/2 * -9.81 * (tf - ti)^2 + yvi * (tf - ti) + yi

Will yield the velocity equation:

y_vel = -9.81 * (tf - ti) + yvi;

taking it again will yield acceleration by itself.

I don't know if you've had calculus and/or physics in the classroom, so here is some other stuff to keep in mind. This is not code, but coders (game developers, actually) will need to know the general principle, of time, behind this to derive code effectively for game physics and scene rendering in general:

Take:

a = (v2 - v1) / (t2 - t1)

Assume that v2 is the velocity at t2 and v1 is the velocity at t1. This is very broad in that if the difference in t2 and t1 is 5 seconds, then we are getting an "average" of the acceleration over that 5 second span of time.

If we rewrite in calculus notation (my calculus writing is unlikely to be precise since it has been a decade and I never kept up):

a = dv/dt

Then take the limit:

a = lim of dv/dt as dt approaches 0

we can find the acceleration at a much finer resolution of time(called the instantaneous acceleration), assuming dt != 0 since that is undefined.

What that means is that if it takes 0.000146 seconds between scene renderings, then dt = 0.000146 seconds and you can take the velocity at the end of the previous scene with the velocity in the current scene to get the acceleration now.

The same principle can be applied to position, velocity, rotation, orbit, etc.

NOTE: the use of the phrase "between scene renderings." That is important because you're doing all your calculations between the renderings and what you render is what all the calculations have added up to. In simple games(tower of hanoi, tic-tac-toe, etc), this is useless info.

In a first person shooter, flight sim, etc, it becomes critical. You'll need need to carry over info from the previous scene calcs. From what I've learned of physics engines in general, they present the results at the top of the game loop and do their calculations at the end. So you end up having the results ready for the next scene.


This is a lot of overkill for a simple arcade game, but maybe not if it explains how do your calculations for a scene, but it is hardly anything for a real physics engine because it doesn't even touch on inertia, moments of inertia, center of mass, force application, etc.
Last edited on
Topic archived. No new replies allowed.