How to Simulate Artificial Gravity in Matter.js
This guide explains how to simulate artificial gravity inside a rotating ring space station using the Matter.js 2D physics engine. You will learn how to disable default directional gravity, construct a hollow circular station using segmented compound bodies, impart continuous angular velocity to the structure, and manage the physics forces that keep objects pinned against the inner hull.
1. Disable Global Gravity
Standard Matter.js worlds apply a downward force along the Y-axis. Because artificial gravity in a space station is directed outward from the center of rotation toward the outer rim, you must first disable the engine's default gravity.
const engine = Matter.Engine.create();
engine.gravity.x = 0;
engine.gravity.y = 0;2. Build the Hollow Ring Station
Matter.js does not support native hollow circle geometry. To build a hollow ring, create a compound body composed of multiple rectangular segments arranged in a circle.
function createRingStation(centerX, centerY, radius, thickness, segments) {
const parts = [];
const angleStep = (Math.PI * 2) / segments;
const segmentLength = 2 * radius * Math.tan(angleStep / 2) + 2; // slight overlap to avoid gaps
for (let i = 0; i < segments; i++) {
const angle = i * angleStep;
const x = centerX + radius * Math.cos(angle);
const y = centerY + radius * Math.sin(angle);
const segment = Matter.Bodies.rectangle(x, y, thickness, segmentLength, {
angle: angle,
isStatic: false,
friction: 0.8, // High friction ensures objects inside are dragged to rotational speed
restitution: 0.0
});
parts.push(segment);
}
return Matter.Body.create({
parts: parts,
isStatic: false,
frictionAir: 0 // Prevent the station from slowing down automatically
});
}3. Pin and Rotate the Station
A free compound body will drift upon contact with other objects. Pin the station to the center of the world using a constraint, and continuously maintain its angular velocity.
const stationCenter = { x: 400, y: 400 };
const station = createRingStation(stationCenter.x, stationCenter.y, 250, 20, 32);
// Pin the station to its center point
const axle = Matter.Constraint.create({
pointA: stationCenter,
bodyB: station,
pointB: { x: 0, y: 0 },
stiffness: 1,
length: 0
});
Matter.Composite.add(engine.world, [station, axle]);
// Maintain constant rotation
const targetAngularVelocity = 0.02; // Adjust speed to increase/decrease centrifugal force
Matter.Events.on(engine, 'beforeUpdate', () => {
Matter.Body.setAngularVelocity(station, targetAngularVelocity);
});4. Handling Artificial Gravity Mechanics
There are two primary methods to produce artificial gravity inside this structure:
Method A: Pure Centrifugal Force (Inertia-Driven)
If the interior rim has sufficient friction, any object placed inside that touches the hull will be accelerated tangentially. Its inertia naturally forces it against the wall, creating a realistic normal force. This requires no extra code; objects simply need adequate surface friction:
const occupant = Matter.Bodies.circle(stationCenter.x + 200, stationCenter.y, 15, {
friction: 0.8,
restitution: 0.1,
density: 0.002
});
Matter.Composite.add(engine.world, occupant);Method B: Radial Gravity Field (Active Assistance)
In digital physics engines, floating objects with zero contact with the rim will not naturally experience centrifugal force. To simulate an outward "pull" toward the rim for all free-floating items, apply a continuous radial force directed away from the station’s center:
Matter.Events.on(engine, 'beforeUpdate', () => {
const bodies = Matter.Composite.allBodies(engine.world);
bodies.forEach((body) => {
// Skip the station segments
if (body === station || station.parts.includes(body)) return;
const dx = body.position.x - stationCenter.x;
const dy = body.position.y - stationCenter.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0 && distance < 240) {
// Normalize vector
const nx = dx / distance;
const ny = dy / distance;
// Centrifugal acceleration: a = omega^2 * r
const forceMagnitude = body.mass * Math.pow(targetAngularVelocity, 2) * distance * 0.5;
Matter.Body.applyForce(body, body.position, {
x: nx * forceMagnitude,
y: ny * forceMagnitude
});
}
});
});Using Method A provides realistic physics where an object must make contact to gain momentum, while Method B produces an intuitive arcade-style gravity field where objects always fall toward the closest section of the outer ring.