How to Simulate Handbrake Slides in Matter.js

This guide explains how to simulate realistic handbrake slides in a top-down Matter.js vehicle by dynamically lowering the lateral friction of the rear wheels. By decomposing the vehicle’s velocity vectors and reducing the counter-force applied against sideways sliding when the handbrake input is engaged, you allow the vehicle's rear end to break traction and swing out under rotational inertia.

Understanding Top-Down Tire Friction

Matter.js is a rigid body physics engine that calculates collisions, but it does not natively simulate tire dynamics on a flat surface. To achieve realistic car movement, tire forces are manually calculated each frame inside the engine's beforeUpdate event.

A tire generates two distinct frictional forces:

  1. Longitudinal Friction: Resistance or drive force along the direction the wheel is pointing (forward/backward).
  2. Lateral Friction: Resistance perpendicular to the wheel direction, preventing the vehicle from sliding sideways.

A handbrake slide occurs when the lateral grip on the rear wheels drops significantly, allowing centrifugal force to slide the rear axle sideways while the front wheels maintain directional control.

Step 1: Decomposing Wheel Velocity

To control lateral friction independently from forward movement, project the wheel's linear velocity onto its local coordinate axes:

// Get wheel directional vectors
const forwardVector = {
    x: Math.cos(wheel.angle),
    y: Math.sin(wheel.angle)
};

const rightVector = {
    x: -Math.sin(wheel.angle),
    y: Math.cos(wheel.angle)
};

// Calculate lateral speed (perpendicular to wheel heading)
const lateralVelocity = (wheel.velocity.x * rightVector.x) + (wheel.velocity.y * rightVector.y);

Step 2: Applying Variable Lateral Resistance

Under normal driving conditions, you cancel out almost all lateral velocity by applying an opposing force. When the handbrake is triggered, reduce this damping factor on the rear wheels:

// Grip coefficients (between 0 and 1)
const normalRearGrip = 0.95;
const handbrakeRearGrip = 0.15;

// Select grip based on handbrake state
const currentGrip = isHandbrakeActive ? handbrakeRearGrip : normalRearGrip;

// Calculate counteracting force to eliminate sideways slide
const lateralImpulse = -lateralVelocity * currentGrip;

const lateralForce = {
    x: rightVector.x * lateralImpulse * wheel.mass * 0.1,
    y: rightVector.y * lateralImpulse * wheel.mass * 0.1
};

// Apply force directly to the rear wheel body
Matter.Body.applyForce(rearWheel, rearWheel.position, lateralForce);

Step 3: Managing Longitudinal Drag

When applying a handbrake, rear wheels do not just lose lateral grip; they lock up. This introduces forward sliding drag rather than free rolling.

if (isHandbrakeActive) {
    // Calculate forward speed
    const forwardVelocity = (wheel.velocity.x * forwardVector.x) + (wheel.velocity.y * forwardVector.y);
    
    // Apply braking drag along the forward axis
    const brakeDrag = -forwardVelocity * 0.05 * wheel.mass;
    const forwardForce = {
        x: forwardVector.x * brakeDrag,
        y: forwardVector.y * brakeDrag
    };
    
    Matter.Body.applyForce(rearWheel, rearWheel.position, forwardForce);
}

Step 4: Stabilizing the Slide

When entering a slide, weight transfer and angular velocity impact how the vehicle behaves. To fine-tune the slide feel: