Muz's Guide to Making a Realistic Physics Engine
Author: | Muz
|
Submitted: | 1st September, 2005
|
Views: | 9404
| Rated: |
|
|
Muz's Guide to Making a Realistic Physics Engine
Difficulty: Very Advanced
Knowledge required:
Arithmetic skills
Basic algebra (why F=ma means that a=F/m)
Basic Click coordinating (X and Y positions)
Enough experience with MMF to understand some of it's more abstract concepts
Knowing how to use the Metric system
Boring intro stuff
This part is mostly to counter some comments you guys might have, so you don't have to bother to read this .
To be honest, I wrote this article mostly to help myself. It's basically the design for my own physics engine. But what better way to get motivation AND a design I can understand other than writing an article on it? Not only do I help myself, but I can help those of you who want to make a realistic physics engine of your own. I'm surprised that I couldn't find an article on this topic in the Click Community, so perhaps it's time for one.
I won't explain every phenomenon in physics in this short article, but I'll tell you what the laws of physics are. All this is just a synopsis of about a semester (14 weeks) + two years of school on physics. If you want to know the full details, take a class on physics.
Another note: This is just basic 2D Newtonian physics. 3D physics requires full knowledge of vectors and stuff, and 'true' molecule-perfect physics would require a lot of annoyingly confusing space-time work. But for most platform games, racing games, top-view, other 2D games that pretend to look 3D, this should more than suffice.
Finally, if you're too lazy to try and code this, don't worry. I'll almost certainly code this physics engine + a few examples sooner or later. Should be finished by the end of September if there's no bugs in the way. But should you not have MMF 1.5, you could try and use this, though MMF 1.2's 4 Alterable Values may give you some trouble.
Formulas
First, here's a list of the basic formulas just to look back at later. I'll explain the units later
m is mass, unit kg
t is time, unit seconds --> Clicksecond
d is distance, unit meters --> pixels
a is acceleration, unit meters/second^2 --> pixels/Clicksecond
v and u are velocity, unit meters/second --> pixels/Clicksecond
F is force, unit N
F=ma
v=d/t
momentum = m*((u-v)^2)
impulse = momentum/t
Understanding basic units and stuff
Units are one of the more complicated parts of doing a physics engine. I'm not surprised if you guys wanna skip this step. You can skip unit conversion if you like, but that means that your distances, speed and stuff might not be accurate with the real world, kinda missing the point of making a realistic physics engine.
But if you REALLY don't want to do accurate unit conversion, I'll just let you know that the only thing it'll screw up is if you want to use pre-existent numbers, like gravity. It won't do much harm to movement, but unless you convert units, you can't have accurate Earth gravity.
To get it to look realistic, you've got to your calculations to the right units. In a real world, we'd be using reliable metric units like meters and seconds to calculate stuff. But in the Click world, the smallest reliable units are pixels and 0.03 of a second.
Yup, the timer's probably a wierd thing to most of you. I've done a few tests (and uploaded them somewhere on TDC) and it seems that MMF can, at best, run an event at about 0.025 seconds. So, to make things perfectly accurate, you have to run every timer-based thing at 0.03 seconds. Just to make things easier to read, 1 Clicksecond = 0.03 seconds.
Distance conversion can be a bit of a problem if not done right. Set a scale. For this example, I'm using 1 meters = 10 pixels. You can make it anything you like, but be sure to base all your calculations on whatever you do. I put the scale number in a global value to save me some trouble of reusing the engine, but you guys can follow your own style.
Actually USING units and stuff
The first part is to make sure you have your timers right. Make sure that every timer-based event uses Every 0.03 s.
To get the distance right, just multiply your meters according to your scale. So, for something 5 meters long with a scale of 10 px/m, you get 50 pixels (Yeah, it's an incredibly tiny scale).
Take a look at that formula list up there again. Note that the units for Force and mass is the real life Newton and kilogram. That's because those units function perfectly well in the Click world. No need to change them.
Also, keep in mind that all units work just fine just as long as you convert them first. That is, as long as you keep everything in pixels and Clickseconds, you won't have to do a conversion. The only times you need to convert units is if you're converting real life seconds and meters into the Click world.
For example, our real life gravity of 9.8 m/(s^2) would have to be converted to px/(Cs^2) if you want to use it in your game. On a scale of 10 px/m, that would make it 9.8*10/(0.03^2)=108889. It sounds wierd, but that's the right answer. Test it in your game if you don't believe me. If you think the number's high, remember that we're working things in 0.03 seconds, not 1 second. Using an Every 1 s condition would make things waay too jerky .
Basic movement
Here's where the real coding starts. Newtonian movement (at least in Click) is basically about 3 things - acceleration, velocity, and distance. See the formulas above if you want formulas.
Acceleration - You normally have to set this, unless you intend to use momentum and force. If you're making a platformer, start with acceleration that pulls down (gravity). Otherwise, you won't be using it much, other than for moving cars.
Velocity - This is where most of the movement works. Jumping means some upward velocity. The downwards acceleration (gravity) will pull the guy back down. Velocity is also used to move your characters left and right.
Distance - How far the thing moves.
Friction, air resistance, etc
Friction is what slows down stuff. Here, we could also apply friction to air resistance, getting tired while running, the water/liquid resistance while swimming, etc. Be creative. There's a lot of things you could do with it.
The force of friction is done by multiplying friction coefficient with the current velocity. A friction coefficient of something is how much it slows things down. The higher it is the more it slows it down. Slippery things like ice on ice would have something close to 0.03. Things like rubber on concrete would have as high as 0.8 or so.
Be sure to add a few events/condition to prevent the object from moving backwards when the total friction is greater than the total movement.
Your movement should be something along the lines of:
Every 0.03 s:
Velocity = Velocity + Acceleration - (Friction coefficient)*Velocity
Set X/Y to [current X/Y position]+[X/Y Velocity]
Set the appropriate alterable values to velocity, acceleration and friction coefficient.
Simple enough, right?
Technically, there's static friction coefficients and kinetic friction. Static is how much friction there is before the thing moves. Kinetic is how much friction slows it down when it's already moving. Wheels and other things that turn use static friction coefficients, not the other one. Nothing important, though. Feel free to just use one type .
If you want some real life friction coefficients, here's some real life tables I found on a Google search: http://www.roymech.co.uk/Useful_Tables/Tribology/co_of_frict.htm
Moving at angles
Sooner or later, you may have to move in more than 4 directions. That's where sine and cosine come in. I know many of you are scared of trigonometry, so to make things simple for both the readers and the writer of this article, I'll just give you all the formula :
(X velocity/acceleration/force/etc) = (Total velocity/acceleration/force/etc)*cos(angle)
(Y velocity/acceleration/force/etc) = (Total velocity/acceleration/force/etc)*sin(angle)
It's simpler than it looks. Though I'm not sure if the angle has to be in degrees or radians. Should be in radians if I'm not mistaken.
Let's say that you have something moving at 50 px/Cs at an angle of 1.2 radians.
X Velocity = 50*cos(1.2)
Y Velocity = 50*sin(1.2)
Very simple
For conversion of degrees to radians:
1 radian = 180/pi degrees
pi = 22/7 = 3.142
So, 1 pi radians is equal to 180 degrees, 90 degrees = 0.5 pi = 1.57 radians, and so on.
Momentum & Force
This part of my engine is still untested yet, so there might be a few mistakes here. But here's how the concept should work.
F=ma, and thus, a=F/m. Force would be the amount of force applied to it from whatever is moving it, engines, legs, whatever. You could move around most things with just velocity, so you might not need this at all for your engines. But if you intend to use momentum, you'll need it.
In click terms:
Every 0.03 s:
X/Y Acceleration = [X/Y Force]/mass
Set some values to acceleration, force, and mass.
Momentum is simply applying decceleration to an accelerating object. A moving object would have a certain amount of Force = mass * acceleration. The acceleration would keep something moving in one direction, even if when the force moves in another, like when driving a car.
Brakes would slow down a car by greatly adding friction to the movement. Momentum doesn't matter much here.
But when you have a space game where there are no brakes, just blasting an engine in the opposite direction, you'll use force to slow down the movement. In this case you'll just be calculating the loss of acceleration by the force in the the opposite direction. In other words
Every 0.03 s:
Acceleration = Acceleration - (Force of brakes/mass)
Impulse, i.e damage
Impulse is hardly necessary in your game, but it'll make damage more realistic. Impulse is the amount of force applied when something hits something else. Formula is m*((u-v)^2)/t. (V, the final velocity would normally be 0, assuming the object stops when it hits something)
In click terms, the t has to be changed. t is how much time the object takes to stop moving. An object hitting hard concrete might stop in just 0.1 seconds, while something hitting a rubber tyre or giant bean bag might take a few seconds to stop. You decide
Thus, the code would be:
Damage = Mass*(Velocity^2)/(slowdown time)
Alterable values should be mass & velocity. Your choice how to deal with damage. Slowdown time could be an alterable value, or it could just be a number if you like.
For example, a 50 kg guy being shot from a cannon at 20px/Cs and hitting a rubber tyre might take 50*(20^2)/5 = 4000 Newtons of damage. Kinda like being hit by a 1 metric ton vehicle moving at 4 km/h. Not so bad.
But if he were hitting a concrete wall that'd take him 0.1 s to stop, it'd be 50*(20^2)/0.05 = 200000 N of damage. Equal to a 1 metric ton vehicle hitting him at 200 km/h. Ouch. Of course, these examples may not be too accurate depending on how stiff the guy is and how strong the wall is, but it's just an example .
Smoothing things out
One last note: Click movement is hardly ever smooth. You'll have to use some loops or (preferably) the Move Safely (2) object to calculate movement pixel-by-pixel. How you'd deal with this is your choice. Sadly, I think non-MMF 1.5 users (and pirates ) would have to rely on loops. But those who do have MMF 1.5 can just wait till I finish coding this engine...
|
|
|