Find Collision Normal Vector in Matter.js
This article explains how to retrieve and utilize the collision normal vector in Matter.js. You will learn which event listener to hook into, where the normal vector is stored within the collision data structures, how to interpret its directional orientation between two colliding bodies, and how to apply this data in your physics simulations.
Listening to Collision Events
To access collision data in Matter.js, attach a listener to the
Engine instance using Matter.Events. The most
common events for detecting impacts are collisionStart and
collisionActive.
Matter.Events.on(engine, 'collisionStart', (event) => {
const pairs = event.pairs;
for (let i = 0; i < pairs.length; i++) {
const pair = pairs[i];
// Access collision data here
}
});Accessing the Normal Vector
Each collision pair contains a collision object that
holds geometric details about the impact. The normal vector is stored
directly in pair.collision.normal.
const normal = pair.collision.normal;
console.log(`Normal X: ${normal.x}, Normal Y: ${normal.y}`);The normal property is a normalized 2D vector object
with x and y coordinates representing a unit
vector (magnitude of 1) perpendicular to the contacting surface.
Interpreting Vector Direction
Matter.js defines the collision normal relative to the two bodies
involved: pair.bodyA and pair.bodyB.
- The normal vector points from
bodyAtowardbodyB. - If you are calculating a bounce, reflection, or force applied to
bodyB, the vector points in the direction of the impact force. - If you are calculating the reaction force on
bodyA, you must negate the vector components (-normal.x,-normal.y) to get the surface normal facingbodyA.
Complete Implementation Example
const { Engine, Render, Runner, Bodies, Composite, Events, Vector } = Matter;
const engine = Engine.create();
// Setup bodies and world...
Events.on(engine, 'collisionStart', (event) => {
event.pairs.forEach((pair) => {
const { bodyA, bodyB, collision } = pair;
const normal = collision.normal;
// Normal pointing from bodyA to bodyB
const normalAtoB = { x: normal.x, y: normal.y };
// Inverted normal for bodyA
const normalBtoA = Vector.negate(normalAtoB);
console.log(`Collision between ${bodyA.label} and ${bodyB.label}`);
console.log('Surface Normal (A -> B):', normalAtoB);
console.log('Surface Normal (B -> A):', normalBtoA);
});
});Key Considerations
- Compound Bodies: If a body is made of multiple
parts,
pair.collision.normalstill represents the resolved contact normal between the specific colliding sub-parts (pair.collision.parentAandpair.collision.parentBresolve to the top-level bodies). - Multiple Contacts: A single pair can have multiple
contact points (accessible via
pair.collision.supports), but Matter.js resolves them into a single primary collision normal for the pair.