Detect Closing Distance in Matter.js with Vector Dot
In physics engines like Matter.js, determining whether two moving
bodies are closing distance is essential for predictive collision
handling, targeting systems, and artificial intelligence behaviors. By
combining the relative position and relative velocity of two bodies, the
Matter.Vector.dot method computes the dot product to
instantaneously evaluate whether the objects are moving toward or away
from each other without requiring expensive square root distance checks
across frames.
The Physics Behind the Dot Product Check
To determine whether two bodies are approaching each other, you need two pieces of information:
- The Relative Position Vector (\(\vec{r}\)): The vector pointing from Body A to Body B.
- The Relative Velocity Vector (\(\vec{v}\)): The velocity of Body B relative to Body A.
The dot product of these two vectors reveals the directional relationship between their relative position and relative motion:
\[\text{Dot Product} = \vec{r} \cdot \vec{v}\]
- Negative Dot Product (\(< 0\)): The relative velocity opposes the displacement vector. Body B is moving toward Body A, meaning the distance between them is decreasing.
- Positive Dot Product (\(> 0\)): The relative velocity aligns with the displacement vector. The bodies are moving away from each other, meaning the distance is increasing.
- Zero (\(= 0\)): The motion is perpendicular to the line connecting the bodies (such as tangential orbit), or the relative velocity is zero. The distance is instantaneously static.
Implementation in Matter.js
Matter.js provides vector utility functions under the
Matter.Vector module, making this calculation
straightforward using Matter.Vector.sub and
Matter.Vector.dot.
// Assume bodyA and bodyB are valid Matter.Body instances
function areBodiesClosing(bodyA, bodyB) {
// 1. Vector pointing from bodyA to bodyB
const relativePosition = Matter.Vector.sub(bodyB.position, bodyA.position);
// 2. Velocity of bodyB relative to bodyA
const relativeVelocity = Matter.Vector.sub(bodyB.velocity, bodyA.velocity);
// 3. Dot product of relative position and relative velocity
const dotProduct = Matter.Vector.dot(relativePosition, relativeVelocity);
// If the dot product is negative, they are closing the distance
return dotProduct < 0;
}Why Use
Matter.Vector.dot Instead of Distance Comparisons?
Tracking distance across successive animation frames requires storing
past positions and calculating distance metrics using the Pythagorean
theorem (Math.hypot or Math.sqrt). This
traditional approach introduces latency because it requires at least two
discrete frames of positional data to detect a trend.
Using Matter.Vector.dot solves this problem by
providing:
- Instant Evaluation: It uses current velocities to identify approach trajectories in a single simulation tick.
- Computational Efficiency: The dot product formula (\(x_1 x_2 + y_1 y_2\)) uses simple multiplication and addition, bypassing the computational overhead of square root functions.