How to Simulate Lunar Gravity in Matter.js
Simulating a realistic lunar landing environment in Matter.js requires modifying the physics world's default environmental constants to mirror the Moon's physical conditions. To achieve this, you must reduce the engine's vertical gravitational scale to roughly 16.6% of Earth's gravity and eliminate air resistance parameters on the spacecraft body. This guide demonstrates how to calibrate the engine's gravity vector, strip away aerodynamic damping, and apply vector-based thruster controls to create an authentic vacuum flight model.
1. Configure the Lunar Gravity Vector
By default, Matter.js initializes the world with standard gravity
directed downward along the Y-axis
(engine.gravity.y = 1).
The Moon's gravitational acceleration is approximately \(1.62\text{ m/s}^2\), roughly one-sixth of
Earth's \(9.8\text{ m/s}^2\). To
reflect this, adjust the y component of the engine's
gravity property or modify its overall scale:
// Option A: Adjust the Y-component relative to default 1.0
engine.gravity.y = 0.165;
engine.gravity.x = 0;
// Option B: Scale the default gravitational constant
engine.gravity.scale = 0.001 * 0.165; // Adjust based on your simulation scaleSetting engine.gravity.y = 0.165 ensures that any
free-falling body accelerates at a rate consistent with the lunar
surface relative to default engine units.
2. Eliminate Atmospheric Drag
The Moon has no atmosphere, meaning objects experience zero
aerodynamic drag. In Matter.js, bodies have an innate
frictionAir property (defaulting to 0.01),
which acts as linear damping against translational and rotational
motion.
When creating the lander vehicle, set frictionAir to
0:
const lander = Matter.Bodies.polygon(x, y, 3, 30, {
density: 0.002,
frictionAir: 0, // Eliminates all atmospheric drag
friction: 0.8, // Surface friction for landing pads
restitution: 0.05 // Low bounciness upon touchdown
});
Matter.Composite.add(engine.world, lander);With frictionAir: 0, the lander will maintain its
velocity and trajectory indefinitely until an external force—such as
thruster output, gravity, or a surface collision—acts upon it.
3. Implement Inertial Thruster Mechanics
Without atmospheric resistance, spacecraft maneuvering relies entirely on Newtonian mechanics (\(F = ma\)). Angular momentum and linear velocity do not decay automatically; stopping a rotation or translation requires an opposing counter-force.
Apply forces using Matter.Body.applyForce directed along
the lander's orientation vector:
function applyMainThruster(lander, power) {
// Determine force direction based on the lander's current angle
const angle = lander.angle - Math.PI / 2;
const force = {
x: Math.cos(angle) * power,
y: Math.sin(angle) * power
};
// Apply force directly at the center of mass
Matter.Body.applyForce(lander, lander.position, force);
}
function applyRotationalThruster(lander, torque) {
// Modifies angular velocity directly to simulate Reaction Control System (RCS) thrusters
Matter.Body.setAngularVelocity(lander, lander.angularVelocity + torque);
}4. Verification and Fine-Tuning
To confirm the vacuum physics implementation is correct:
- Verify Trajectory: Fire the main thrusters diagonally, then cut power. The lander must trace a true parabolic arc influenced only by gravity, without deceleration in horizontal speed.
- Verify Angular Momentum: Rotate the craft using RCS controls. If torque is applied once, the craft must continue spinning at a constant angular velocity until an equal and opposite torque is applied to stabilize it.