Newton's Gravity Between Two Bodies in Matter.js

This article explains how to simulate mutual gravitational attraction between two bodies in Matter.js using Newton's law of universal gravitation. You will learn how to disable standard engine gravity, calculate the distance and directional vectors between bodies, compute the gravitational force magnitude, and apply equal and opposite forces on each simulation step.

The Gravitational Formula

Newton's law of universal gravitation states that the attractive force (\(F\)) between two masses (\(m_1\) and \(m_2\)) is proportional to their masses and inversely proportional to the square of the distance (\(r\)) between their centers:

\[F = G \frac{m_1 m_2}{r^2}\]

In a physics engine:

1. Disable Engine Gravity

Matter.js applies a default downward gravity across the entire world. To simulate orbital or mutual celestial mechanics, set the global gravity to zero:

engine.gravity.scale = 0;

2. Calculate and Apply the Force

Mutual attraction requires updating the applied forces before every engine step. Use the beforeUpdate event provided by Matter.Events to calculate and apply forces iteratively.

const { Engine, Render, Runner, Bodies, Composite, Body, Events, Vector } = Matter;

// Initialize engine and world
const engine = Engine.create();
engine.gravity.scale = 0;

// Create two bodies
const bodyA = Bodies.circle(300, 300, 30, { mass: 1000 });
const bodyB = Bodies.circle(500, 300, 15, { mass: 10 });

Composite.add(engine.world, [bodyA, bodyB]);

// Gravitational constant tuned for screen coordinates
const G = 0.001;
// Softening factor to prevent infinite acceleration at close range
const minDistance = 10;

Events.on(engine, 'beforeUpdate', () => {
    // Determine the displacement vector from bodyA to bodyB
    const dx = bodyB.position.x - bodyA.position.x;
    const dy = bodyB.position.y - bodyA.position.y;
    
    // Calculate distance
    const distanceSquared = dx * dx + dy * dy;
    const distance = Math.max(Math.sqrt(distanceSquared), minDistance);

    // Calculate Newton's gravitational force magnitude
    const forceMagnitude = (G * bodyA.mass * bodyB.mass) / (distance * distance);

    // Normalize displacement to produce a unit vector, then multiply by magnitude
    const forceVector = {
        x: (dx / distance) * forceMagnitude,
        y: (dy / distance) * forceMagnitude
    };

    // Apply attraction to bodyA toward bodyB
    Body.applyForce(bodyA, bodyA.position, forceVector);

    // Apply equal and opposite reaction to bodyB toward bodyA
    Body.applyForce(bodyB, bodyB.position, {
        x: -forceVector.x,
        y: -forceVector.y
    });
});

Considerations for Stability