I'm thinking of making a lander game, where you control a spaceship and need to land it without crashing. What is a simple formula to calculate speed of falling or acceleration with relation to working time to time engines?
3 Answers
The simplest way is the Euler integration. You have to store position vector and velocity vector. At each frame:
- measure the time passed since the last integration step: dt
- compute the force vecor due your engines: F
- compute the acceleration vector: A = F/m where m is the spaceship mass.
- add the gravity vector: A = A + G make sure that G points toward the planet's center
- update the velocity vector V = V + A·dt
- update the position vector X = X + V·dt
(x for scalars, X for vectors)
be sure that dt is small...
|G| is about 9.8 m/s² for earth and about 1.6 m/s² for moon
in general the actraction Force due the gravital interaction is:
It affects each body and it points toward the other one.
The G scalar is the very famous Gravitational constant it is about 6.67e-011 N(m/Kg)²
Since you are interested in acceleration:
You only need to know the planet's mass (m2) and radius (r) to compute your acceleration.
Typically the acceleration that moves the planet toward your spaceship is negligible because usually m1 is negligible compared to m2.
However, if you are trying to land to a small asteroid you probably have to use the general formula adding that force to the total force vector in the second step.
EDIT:
As required some hint on implementation. You will need:
- A vector library
- Engine Model
- Phisics Model
- Collision Detection
- User Interface (input and graphic rendering)
First of all the vector library: your game can be mono/bi/tree/four... dimentional, as far as you consider your case to be a projection of a 3D word, the physical roules hold.
If n is the dimension you choose (probably 2 or 3 in your case), the library must have:
- a vector storage entity (a list of n floating point numbers for each vector)
- a sum operator (sum component by component)
- a scalar multiplication operator (each component multiplied by a float)
- a dot-multiplication between vectors (multiplicate component by component and sum up all)
- the vector length (square root of a vector dot-mutiplied by itself)
You can use a library that does this or implement one by yourself; a vector can be a struct or a class, the choice is yours.
Each engine should be described by:
- a vector indicating its thrust strength and direction
- a scalar that indicates the fuel usage per second when on full power;
your user input will be used to provide to each engine a number that will be between 0 (unused engine) and 1 (full power): the engine (usage) factor.
Multiply the engine factor for its thrust vector to obtain the engine real trust and sum up all the results of all the available engines; this will give you the F of the second step.
Your engine factor can be used to know the real fuel usage for each engine: multiply the engine factor by the fuel usage and by dt to know the instantaneous fuel usage; you can substract this value from the total fuel capacity variable (this gives you the opportunity to update your total mass m if the fuel mass is considerable).
Now you can proceed using the integration to compute the new position, check for the collision with your planet surface; if any, use the length of the velocity vector to say if the landing was a success or a disaster.
Obviously other collision checks can/should be made, some surface entities cant be allowed as landing point so every collision is a fatal one.
I leave how to get input and how to render your spaceship to you; you can use the engine factor to render the engine status frame by frame, for example.
-
\$\begingroup\$ That is great, but some ideas how to impelement it in code would be great. \$\endgroup\$– DvoleCommented Jul 14, 2011 at 18:39
-
1\$\begingroup\$ where I learned physics shiffman.net/teaching/nature \$\endgroup\$ Commented Jul 14, 2011 at 20:49
-
-
As the other excellent answer seems a bit theoretical, here's the simple code version:
// Position of the lander:
var positionX = 100.0;
var positionY = 100.0;
// Velocity of lander
var velocityX = 0.0;
var velocityY = 0.0;
// Acceleration due to gravity
var gravity = 1.0;
// If the player is pressing the thrust buttons
var isThrusting = false;
var isThrustingLeft = false;
var isThrustingRight = false;
// Thrust acceleration
var thrust = -2.0;
// Vertical position of the ground
var groundY = 200.0;
// Maximum landing velocity
var maxLandingVelocity = 3.00;
onUpdate()
{
velocityY += gravity;
positionX += velocityX;
positionY += velocityY;
if (isThrusting)
{
velocityY += thrust;
}
if (isThrustingLeft)
{
velocityX += thrust;
}
else if (isThrustingRight)
{
velocityX -= thrust;
}
if (positionY >= floorY)
{
if (velocityY > maxLandingVelocity)
{
// crashed!
}
else
{
// landed successfully!
}
}
}
-
2\$\begingroup\$ Keeping it simple. I expect this is along the lines of what he was looking for. \$\endgroup\$– BeskaCommented Jul 20, 2011 at 20:34
Unfortunately, the math here gets hairy. FxIII's answer is fine for the general case of a falling object but you are talking about a rocket--and rockets burn off fuel.
I have seen code that does it but it was completely undocumented and I never managed to figure out the math behind it. Unless you're CPU-limited somehow I wouldn't bother and simply brute force it--FxIIIs approach applied on a quite short timescale and adjust the thrust (or fuel use if you figure the rocket throttles back as the fuel burns off to maintain the specified acceleration rather than the specified thrust) between each iteration as the rocket burns off fuel.
-
\$\begingroup\$ Going out of fuel just represents a falling parameter. It's simply a vectorial force with decreasing value. Am I wrong? In a simple case you have G against F, where F is the engine of the rocket and G the earth's gravition: In this case you simply have to measure both against each other, so if no fuel is left F falls to 0 so you only have to apply G as vectorial force to your object. Works for every value of F. As long as F >= G the object "should" move in direction of F. \$\endgroup\$ Commented Jul 14, 2011 at 23:56
-
2\$\begingroup\$ @daemonfire300: You misunderstand--I'm not talking about the effect of running out of fuel, but the effect of burning fuel. A constant throttle setting on your engine produces a continuously climbing acceleration figure, a constant acceleration produces a continuously declining fuel burn rate. This means the simple calculations that FxIII gives will produce incorrect fuel use numbers. \$\endgroup\$ Commented Jul 15, 2011 at 2:20
-
\$\begingroup\$ The amount of acceleration gain from A=F/M as fuel is burned is going to be a negligible value unless either the proportion of fuel mass to vehicle is absurdly high or fuel burn rate is similarly high. This is a game, after all. \$\endgroup\$ Commented Jul 16, 2011 at 0:22
-
\$\begingroup\$ @Patrick Hughes: The amount of fuel carried by any true rocket lander (I'm not counting the Mars aerobrake/rocket hybrid cases) is a substantial portion of it's total weight. Assuming the fuel:acceleration ratio to be fixed will produce a very wrong answer. \$\endgroup\$ Commented Jul 16, 2011 at 1:25
-
1\$\begingroup\$ This is not an answer to the question, just a comment on @FxIII's answer. \$\endgroup\$ Commented Jul 26, 2011 at 12:49