Create Speed Booster Strips in Matter.js

This article explains how to build interactive speed booster strips in Matter.js that accelerate dynamic bodies upon contact. By configuring static sensor bodies and listening to collision events, you can detect intersecting objects and programmatically apply directional force or set their velocity to propel them forward.

1. Define the Booster Strip as a Sensor

To allow dynamic bodies to pass over a booster strip without deflecting or bouncing off it, define the booster body with the isSensor: true property. You can also label it so it can be easily identified inside collision event listeners.

const booster = Matter.Bodies.rectangle(400, 500, 200, 40, {
  isStatic: true,
  isSensor: true,
  label: 'boosterStrip',
  angle: 0, // In radians; determine the direction of the boost
  render: {
    fillStyle: '#00ffcc'
  }
});

Matter.Composite.add(engine.world, booster);

2. Listen to Collision Events

Use Matter.js's collisionActive event rather than collisionStart if you want the strip to continuously accelerate the body as long as it remains on the strip. If you want an instantaneous single-frame impulse, use collisionStart.

Matter.Events.on(engine, 'beforeUpdate', () => {
  // Optional: Frame-rate independent physics updates can go here
});

Matter.Events.on(engine, 'collisionActive', (event) => {
  event.pairs.forEach((pair) => {
    const { bodyA, bodyB } = pair;

    if (bodyA.label === 'boosterStrip') {
      applyBoost(bodyA, bodyB);
    } else if (bodyB.label === 'boosterStrip') {
      applyBoost(bodyB, bodyA);
    }
  });
});

3. Apply Directional Force or Velocity

Once a target body is confirmed to be on the booster, accelerate it in the direction the strip is facing. You can achieve this with either Matter.Body.applyForce (for natural acceleration) or Matter.Body.setVelocity (for fixed speed).

Using force application:

function applyBoost(boosterBody, targetBody) {
  if (targetBody.isStatic) return;

  const boostMagnitude = 0.05 * targetBody.mass;
  const angle = boosterBody.angle;

  // Calculate forward vector based on the booster's angle
  const force = {
    x: Math.cos(angle) * boostMagnitude,
    y: Math.sin(angle) * boostMagnitude
  };

  Matter.Body.applyForce(targetBody, targetBody.position, force);
}

Using direct velocity modification:

function applyInstantBoost(boosterBody, targetBody) {
  if (targetBody.isStatic) return;

  const speed = 15;
  const angle = boosterBody.angle;

  Matter.Body.setVelocity(targetBody, {
    x: Math.cos(angle) * speed,
    y: Math.sin(angle) * speed
  });
}

Continuous forces applied inside collisionActive can cause bodies to accelerate excessively if they remain on long strips. Implement a velocity clamp on the target body to maintain controlled movement:

const maxSpeed = 20;
const currentSpeed = Matter.Vector.magnitude(targetBody.velocity);

if (currentSpeed > maxSpeed) {
  const normalized = Matter.Vector.normalise(targetBody.velocity);
  Matter.Body.setVelocity(targetBody, {
    x: normalized.x * maxSpeed,
    y: normalized.y * maxSpeed
  });
}