Custom Gravity for Specific Bodies in Matter.js
This article explains how to override default global gravity in Matter.js to apply custom directional forces to individual rigid bodies. Because Matter.js applies its world gravity settings across all non-static bodies by default, achieving independent gravity requires neutralizing the global gravitational pull on the target body inside the simulation loop and manually applying your desired custom force vectors.
Understanding Matter.js Gravity Mechanics
Matter.js calculates gravitational acceleration globally via the
engine.gravity object. During each simulation step, the
engine applies a force proportional to each dynamic body's mass:
\[\text{Force}_y = \text{body.mass} \times \text{engine.gravity.y} \times \text{engine.gravity.scale}\]
Because bodies lack a native ignoreGravity property, you
must hook into the simulation's update loop to counteract this automatic
calculation before physics integration occurs.
Neutralizing World Gravity and Applying Custom Forces
The standard method is listening to the beforeUpdate
event on the Matter.Engine. During this event, calculate
the exact inverse of the world gravity force, combine it with your
desired custom gravity vector, and apply the resulting net force using
Matter.Body.applyForce.
const { Engine, Events, Body, Vector } = Matter;
// Target body configuration
const customBody = Bodies.circle(400, 200, 30, {
// Custom gravity direction and strength
customGravity: { x: 0, y: -0.001 }
});
// Hook into beforeUpdate
Events.on(engine, 'beforeUpdate', () => {
const gravity = engine.gravity;
// 1. Calculate the counter-force to negate world gravity
const counterForce = {
x: -customBody.mass * gravity.x * gravity.scale,
y: -customBody.mass * gravity.y * gravity.scale
};
// 2. Define custom gravity force scaled by mass
const customForce = {
x: customBody.mass * customBody.customGravity.x,
y: customBody.mass * customBody.customGravity.y
};
// 3. Combine forces and apply to body center
const netForce = {
x: counterForce.x + customForce.x,
y: counterForce.y + customForce.y
};
Body.applyForce(customBody, customBody.position, netForce);
});Alternative Approach: Zero Global Gravity
If multiple bodies in your simulation require distinct gravities, orbital mechanics, or localized point attractors, consider setting global gravity to zero entirely:
engine.gravity.scale = 0;With world gravity disabled, no counteracting math is needed. You can
iterate through all active bodies in beforeUpdate and
directly apply whatever individual gravity vectors each entity
requires.