462 lines
16 KiB
Plaintext
462 lines
16 KiB
Plaintext
|
|
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
|