Perfectly Elastic Collisions in Matter.js

This guide explains how to configure physics bodies and simulation settings in Matter.js to achieve perfectly elastic collisions. In a perfectly elastic system, colliding bodies conserve total kinetic energy, rebounding without any loss of speed or momentum. Achieving this behavior requires setting maximum restitution, eliminating all forms of friction and drag, and tuning the simulation engine to prevent subtle numerical energy losses.

Configure Body Restitution

The core property governing bounce in Matter.js is restitution. A value of 0 represents a completely inelastic collision where bodies stick together, while a value of 1 represents a fully elastic collision.

When two bodies collide, Matter.js calculates the resulting bounce using Math.max(bodyA.restitution, bodyB.restitution). While setting one body to 1 is technically sufficient for collisions involving that body, you should explicitly set restitution: 1 on all interacting bodies—including walls and boundaries—to ensure consistent elastic behavior throughout the entire canvas.

const elasticBody = Matter.Bodies.circle(x, y, radius, {
  restitution: 1
});

Eliminate Friction and Drag

Even with maximum restitution, bodies will lose energy if friction is present. You must strip away linear surface friction, static friction, and air resistance:

Combine these values into a standard definition for your elastic bodies:

const defaultElasticOptions = {
  restitution: 1,
  friction: 0,
  frictionAir: 0,
  frictionStatic: 0
};

const ballA = Matter.Bodies.circle(100, 200, 20, defaultElasticOptions);
const ballB = Matter.Bodies.circle(300, 200, 20, defaultElasticOptions);
const wall = Matter.Bodies.rectangle(400, 200, 50, 400, {
  isStatic: true,
  ...defaultElasticOptions
});

Adjust Engine and Solver Settings

Matter.js uses an iterative impulse solver. In high-speed scenarios or dense clusters of objects, default engine thresholds can introduce minor energy drift (either damping the motion or artificially adding energy).

To maintain energy conservation:

  1. Disable Gravity: If gravity is active, bodies will accelerate downward. Set engine.gravity.y = 0 and engine.gravity.x = 0 if you want closed-system kinetic conservation.
  2. Increase Solver Iterations: Increase engine.positionIterations and engine.velocityIterations (e.g., from default 6 and 4 up to 10 or higher) to minimize calculation errors during impacts.
  3. Disable Sleeping: Set enableSleeping: false on the engine to prevent bodies with low velocities from falling asleep and halting unexpectedly.
  4. Cap Maximum Velocity (Optional): If numerical errors cause bodies to slowly gain energy over thousands of frames, manually clamp body velocities in a beforeUpdate event listener to ensure strict physical consistency.