If you find this article contains errors or problems rendering it unreadable (missing images or files, mangled code, improper text formatting, etc) please contact the editor so corrections can be made. Thank you for helping us improve this resource |
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
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.
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)
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:
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.
v = v0 + a*t
The current velocity equals the initial velocity plus acceleration times time.
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:
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:
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.