Apply Explosive Radial Impulse in Matter.js
This article explains how to simulate an explosive radial impulse in
Matter.js that diminishes in strength over distance. Because Matter.js
lacks a built-in radial explosion tool, you must iterate over active
bodies, determine their proximity to an epicenter, calculate a decaying
force vector based on distance, and apply that force using
Matter.Body.applyForce.
Step 1: Define the Explosion Parameters
To simulate a blast, establish the epicenter coordinate, the maximum effective blast radius, and the peak force applied to objects at point-blank range.
const blastEpicenter = { x: 400, y: 300 };
const blastRadius = 250;
const blastPower = 0.05; // Matter.js forces are typically small valuesStep 2: Query Affected Bodies
Retrieve the list of dynamic bodies in your physics world. You can
query every dynamic body in your engine's Composite or use
Matter.Query.point or Matter.Query.region to
filter bodies within an approximate bounding box before performing
distance checks.
const bodies = Matter.Composite.allBodies(engine.world);Step 3: Calculate Radial Vector and Distance Decay
For each body, find the distance between its center of mass
(body.position) and the blast epicenter. If the distance is
less than the blast radius and greater than zero, calculate the force
decay.
A linear decay model uses a multiplier of
1 - (distance / blastRadius). You can also use an
inverse-square model (1 / (distance * distance)) for a
sharper drop-off.
function applyRadialImpulse(engine, epicenter, radius, power) {
const bodies = Matter.Composite.allBodies(engine.world);
for (let i = 0; i < bodies.length; i++) {
const body = bodies[i];
// Ignore static bodies or sensors
if (body.isStatic || body.isSensor) continue;
const deltaX = body.position.x - epicenter.x;
const deltaY = body.position.y - epicenter.y;
const distance = Math.hypot(deltaX, deltaY);
// Only apply force within the blast radius
if (distance > 0 && distance < radius) {
// Linear falloff: 1 at epicenter, 0 at outer edge
const decay = 1 - distance / radius;
// Normalize direction vector
const normalX = deltaX / distance;
const normalY = deltaY / distance;
// Scale force by decay factor and mass if uniform acceleration is preferred
const forceMagnitude = power * decay;
const force = {
x: normalX * forceMagnitude,
y: normalY * forceMagnitude
};
// Apply the force at the body's center of mass
Matter.Body.applyForce(body, body.position, force);
}
}
}Step 4: Applying the Impulse
Matter.js forces are applied per step. Calling
applyRadialImpulse on a single update frame acts as an
impulse. If you want lighter bodies to travel at the same velocity as
heavier bodies, multiply forceMagnitude by
body.mass. If you want lighter bodies to be launched
further, omit the mass multiplier so that smaller masses experience
greater acceleration (\(a = F /
m\)).