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:

  1. The Relative Position Vector (\(\vec{r}\)): The vector pointing from Body A to Body B.
  2. 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}\]

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: