Gravity Faq
The information contained in document will allow you to realistically
simulate jumping and interstellar maneuvers.
The purpose of this document is to understand the physics of the
world we live in, and apply realistic physics to your game. It
will not give you optimized routines for your program, that is your
job! But if you understand how things work, it will be a heck of
a lot easier.
=====================================================================
= Basics
=====================================================================
There are some key terms I will define to make sure we are talking
about the same things:
Distance : Total path of travel.
Displacement: Difference between original position, and final position
Speed : Change in displacement divided by the change in time
Velocity : Direction of travel, and speed of travel.
Acceleration: Change in velocity divided by the change in time.
Force :
Note: That displacement, velocity, and acceleration are actually
vector quantities. (That is, they have a direction and magnitude).
Abbreviations:
a : acceleration
M : mass
s : displacement
s0 : initial displacement
t : time
v : velocity
v0 : initial velocity
units
m : meter (unit of length)
m/s : meter per second (unit of speed)
m/s^2 : meter per second squared (unit of acceleration)
N : Newtons (unit of force)
s : second (unit of time)
=====================================================================
= The concepts
=====================================================================
Imagine a spaceship flying through space at 1000 m/s. It is deep in
interstellar space with nothing around it. What forces are acting
on it? The answer: none!
It will continue to fly through space at 1000 m/s forever if no
force acts on it.
: The ONLY reason why objects will change velocity (direction and/or
: speed) is if a force is applied to it.
What is a force you ask? A force is an external push or pull. A
force is also a vector. It has a magnitude and a direction
associated with it. Right now gravity is exerting a force on you:
it is pulling you toward the center of the earth.
Also, the only reason an object will change displacement is if
it has some velocity.
Suppose now that the hand of god reaches down and starts pushing the
spaceship forward. There is now a force applied to the ship. With
any force applied, an acceleration is induced. With our new
acceleration, the velocity starts to increase. If god doesn't stop
pushing the ship, then soon the ship will go very fast!
=====================================================================
= Look, I just want to make my guy jump.
=====================================================================
Ok, I'm getting to this. We have our jumping dude Joe. Joe's
initial position is on the floor or platform that is not moving.
The user presses a key and Joe should leap into the air. You need
to keep track of three things about Joe: His position, velocity,
and acceleration.
Initially, his position will be at the floor. Once the key is hit,
we simply give Joe a very fast velocity in the upward direction.
Then every frame/sec/update/whatever decrease his upward velocity
by a constant amount. That's it!
The constant decrease is actually an acceleration in the downward
direction. The horizontal motion of Joe is unaffected. So while
Joe is flying through the air, you can change his forward/backward
movement as normal.
Side note: In real life, it is impossible to move forward/backward
when jumping straight up. But I find games that allow forward/
backward movement while jumping more playable and fun than just jumping
straight up. And who said games are realistic anyway?
What should be the acceleration that we are applying? On earth, the
acceleration of Joe will be 9.81 m/s^2 in the downward direction.
Unfortunately, meters per second squared means nothing to the computer.
The acceleration must be determined based on your game's update rate.
Usually guessing and tweaking is the best way to achieve this.
So our pseudo-code is as such:
Joe.pos.y = 0; (Or wherever floor is)
Joe.vel.y = 0;
Joe.accel = 10;
Joe.jumping = NO;
Loop
If (jump key is pressed)
{
Joe.vel.y = 100;
Joe.jumping = YES;
}
if (Joe.jumping == YES) /* Move Joe if we are jumping */
{
Joe.vel.y = Joe.vel.y - Joe.accel
Joe.pos.y = Joe.pos.y + Joe.vel.y
}
if (Joe.pos.y <= 0) /* Check to see if Joe has hit floor */
{
Joe.vel.y = 0;
Joe.jumping = NO;
}
End Loop
For the first time the jump key is pressed, the position of Joe will
suddenly jump off the floor.
As he goes higher, Joe begins to slow down because the velocity
is constantly decremented. Joe will eventually stop moving up, and
begin to move down. He will move faster and faster until
he reaches the floor again.
Joe's velocity and position in the y direction at the end of each loop
will appear as such:
Loop0 : Joe.vel.y = 0 Joe.pos.y = 0
Loop1 : Joe.vel.y = 100 Joe.pos.y = 100
Loop2 : Joe.vel.y = 90 Joe.pos.y = 190
Loop3 : Joe.vel.y = 80 Joe.pos.y = 270
Loop4 : Joe.vel.y = 70 Joe.pos.y = 340
Loop5 : Joe.vel.y = 60 Joe.pos.y = 400
Loop6 : Joe.vel.y = 50 Joe.pos.y = 450
Loop7 : Joe.vel.y = 40 Joe.pos.y = 490
Loop8 : Joe.vel.y = 30 Joe.pos.y = 520
Loop9 : Joe.vel.y = 20 Joe.pos.y = 540
Loop10: Joe.vel.y = 10 Joe.pos.y = 550
Loop11: Joe.vel.y = 0 Joe.pos.y = 550
Loop12: Joe.vel.y = -10 Joe.pos.y = 540
Loop13: Joe.vel.y = -20 Joe.pos.y = 520
Loop14: Joe.vel.y = -30 Joe.pos.y = 490
Loop15: Joe.vel.y = -40 Joe.pos.y = 450
Loop16: Joe.vel.y = -50 Joe.pos.y = 400
Loop17: Joe.vel.y = -60 Joe.pos.y = 340
Loop18: Joe.vel.y = -70 Joe.pos.y = 270
Loop19: Joe.vel.y = -80 Joe.pos.y = 190
Loop20: Joe.vel.y = -90 Joe.pos.y = 100
Loop21: Joe.vel.y =-100 Joe.pos.y = 0
Notice that Joe is going very fast when he hits the floor.
If Joe does not hit the floor, or the floor disappears (i.e. he jumps
off a platform) then eventually Joe will be going very fast.
We need to give him a limiting velocity. This is the fastest velocity
Joe can go by falling. In real life this is caused by air resistance.
This is easy enough to do.
The modified pseudo-code is such:
Joe.pos.y = 0; (Or wherever floor is)
Joe.vel.y = 0;
Joe.accel = 10;
Joe.jumping = NO;
Loop
if (jump key is pressed)
{
Joe.vel.y = 100;
Joe.jumping = YES;
}
if (Joe.jumping == YES) /* Move Joe if we are jumping */
{
if (Joe.vel.y > -100) /* Limit Joe's velocity to -100 */
{
Joe.vel.y = Joe.vel.y - Joe.accel
Joe.pos.y = Joe.pos.y + Joe.vel.y
}
}
if (Joe.pos.y <= 0) /* Check to see if Joe has hit floor */
{
Joe.vel.y = 0;
Joe.jumping = NO;
}
End Loop
The added loop will not decrease Joe's velocity if he is already moving
downward at a speed of -100. Thus we have added his limiting velocity.
=====================================================================
= Other dimensions
=====================================================================
Ok, the above example is all well and good, but some game sprites
do not just go up and down. Some go side to side while they are
jumping.
Easy! It just so happens that the x and y values of velocity and
acceleration are independent! So while you resolve the y position
and velocity of Joe, you can move Joe in the x direction normally.
It will appear that Joe follows a parabolic path, which is what he
would follow in the real world.
The same goes for 3 dimensions. x,y,z velocities and accelerations are
all independent of one another.
=====================================================================
= Spaceman Spiff
=====================================================================
Another example where kinematics applies is an asteroids type game.
You fly around in a zero-g environment, but can thrust forward in
any direction.
In this case gravity is not a factor. What do we use instead? We
use the thrust of the spaceship as our acceleration. We simply break
up our acceleration vector into x and y directions, and apply the same
techniques as above.
To implement this we get the pseudo-code:
pos.x = 0; pos.y = 0;
vel.x = 0; vel.y = 0;
acc.x = 0; acc.y = 0;
Loop
if (thrust key pressed)
{
resolve_direction_vector;
acc.x = scale_x * 10;
acc.y = scale_y * 10;
}
vel.x = vel.x + acc.x;
vel.y = vel.y + acc.y;
pos.x = pos.x + vel.x;
pos.y = pos.y + vel.y;
End Loop
Now we have a step we have not seen before: resolve_direction_vector.
We need this because the ship can move in any direction.
What this step does is get the appropriate directions vector and
break it down into an x vector and y vector. Once broken down, the
resolve_direction_vector step will set scale_x and scale_y.
/^
Original / |
acceleration / |
vector / |
/ |
/ | Y vector
/ |
Start / * |
position -> X------->|
X vector
* = Angle of ship measured from x axis
Given an angle for our direction from 0 to 365, we can determine
the scale_x and scale_y variables. There are various ways to
do this, but an easy way (not optimized) is to use trig:
scale_x = cos(angle);
scale_y = sin(angle);
The trig functions will take care of negative values. That is, if
the ship is facing West (angle = 180 degrees), the values for
scale_x and scale_y: scale_x = -1; scale_y = 0;
And our ship will accelerate in the negative x direction.
How about if the ship is pointed in a Northeast direction (angle = 45)?
We get:
scale_x = .707
scale_y = .707
Which means the ship is accelerating by 7.07 in the y direction, and
by 7.07 in the x direction. The illusion you see the ship
accelerate by 10 in a 45 degree direction.
You will want to limit the maximum velocity of the ship, or else
it will soon be going faster than the user can see.
If you want, some people like a damping field. That means eventually,
the ship slows down by itself. To do this, simply decrement the
velocity towards zero every loop. (e.g. if velocity is positive,
subtract; if velocity is negative, add)
=====================================================================
= The REAL equations
=====================================================================
This section explains the real equations. If you wish to do some
more complex kinematics, this section will give you everything you
need to resolve the equations. If not, then the above text is
plenty for a lot of applications. For more explanations, consult
a basic physics book.
We define three key variables with respect to an object:
displacement, velocity, and acceleration.
Force is related to acceleration in the following way:
(Incidentally, Newton's second law of motion)
;Eqn 1
;
; F = M * a
;
In English: Force equals mass times acceleration.
So in our spaceship example, the hand of god can cause a small
interceptor with little mass to accelerate faster than a huge
dreadnought with much mass.
The relationship between displacement, velocity, and acceleration
are:
;Eqn 2
;
; s = s0 + v0*t + 0.5*a*t^2
;
The current displacement is equal to the initial displacement, plus
the velocity times time, plus one-half times acceleration times
time squared.
;Eqn 3
;
; v = v0 + a*t
;
The current velocity equals the initial velocity plus acceleration
times time.
;Eqn 4
;
; v^2 - v0^2 = 2*a*s
;
The current velocity squared minus the initial velocity equals two
times acceleration time displacement.
With these 4 magic equations, almost all physics motion problems
can be resolved.
These equations are all based on constant acceleration (which fits
in fine with most computer applications)
=====================================================================
= How do these equations work?
=====================================================================
Let us take a ball thrown directly up into the air. This is a
one-dimensional situation, because the ball is only going up or
down. Let's take s0 to be the position where we release the ball
up into the air. Since we have an initial position, I'm going to
be referring to the current displacement of the ball as position.
The term position will be reference from s0.
Ok, so we throw the ball up into the air. The instant we release
the ball (t = 0) we know:
s0 = 0;
v0 = 10 m/s in the up direction (about 22 miles per hour)
a = ?
Hmm. What is the acceleration? For any object near the earth's
surface, the force due to gravity can be found with:
;Eqn 5
;
; Fg = M*g
;
Where M is the mass and g is the gravitational constant.
For earth, g = 9.81 m/s^2.
A bit of math now. Combine Eqns 1 & 5
;
; Fg = M*a -> M*g = M*a -> g = a
;
Whoa! The masses seem to have canceled! That's interesting. For
any falling object, the acceleration is not affected by the mass.
Does this mean that a hippo will fall as fast as a Ping-Pong ball?
Yes they will: in a vacuum. But I digress...
So the acceleration of the ball equals g, or 9.81 m/s^2.
But the acceleration is in the DOWNWARD direction, so we say a = -g
Using Eqn 3, we get:
v = v0 + a*t = 10 m/s + (-9.81 m/s^2) * 0 s = 10 m/s.
If we use Eqn 2, we also get s = 0. Big deal, huh?
Let's take a look at 0.5 sec later:
v = 10 + (-9.81) * 0.5 s = 5.1 m/s
The ball has slowed down, which is what we expect. Eventually it
will stop. To find this, we simply set v = 0 and solve for t.
v = 0 = 10 + (-9.81) * t
Solving for t, we find t = 1.019 seconds. Thus 1.019 seconds after
we throw the ball up, it stops in mid-air.
Ok, we know it stops, but where is it? To find this, we use Eqn 2:
s = 0 + 10 * 1.019 + 0.5 * (-9.81) * 1.019^2 = 5.1 meters
That is 5.1 meters above the spot where we released it.
What goes up must come down, but how fast? How fast is our ball
going when we catch it? When we catch the ball, we know that
s = 0. So use Eqn 4. After some calculations, we find
v = sqrt( v0^2 ). That's easy, right? v = v0. Well...sort of.
There is actually two solutions to this equation. +v0 and -v0.
What does this mean? It means whenever the ball is at position
s = 0, then it is either going up at v0 or down at v0. Since
we know it was going up when we threw it, it must be coming down
at the same velocity.
The last thing we find is what time it comes down:
Use Eqn 3:
v = -v0 = v0 + (-9.81) * t
Result: t = 2.038 seconds. If we throw a ball up at 10 m/s, then
2.038 seconds later, we will find the same ball in our hand.
This section was just to show how the equations work. In an
actual program, you wouldn't simply stick these equations in because
you would have to keep track of t for every single object. Every time
something jumped, you'd reset that object's personal t.
=====================================================================
= Hasta La Vista, dudes
=====================================================================
Well, that's it. Hope this gives you enough information to start out.
If you have questions, suggestions, clarifications, and any other
modifications, please drop me a line.
Edgar Roman
eroman@nmsu.edu
or (aroman@nmsu.edu)
First Release: 12/29/94