Chameleon Tongue Projection in Matter.js

This article explains how to simulate the biomechanical catapult mechanism of a chameleon's tongue using the Matter.js 2D physics engine. By combining rigid bodies, high-stiffness spring constraints, and a programmatic latch release system, you can replicate the rapid conversion of stored elastic potential energy into high-velocity ballistic projection.

Biomechanical Principle

A chameleon does not project its tongue through instantaneous muscle contraction. Instead, it slowly loads energy into elastic collagen sheaths surrounding the entoglossal bone (an elastomeric spring) and holds it with a biological latch. When the latch releases, the stored elastic strain energy rapidly propels the tongue forward at extreme accelerations.

In Matter.js, this translates to:

  1. An anchor point (chameleon head).
  2. A projectile body (tongue tip).
  3. A primary elastomeric spring constraint with high stiffness.
  4. A temporary latch constraint to hold the spring in tension.
  5. Removal of the latch constraint to execute the ballistic release.

Setting Up the Engine and Bodies

First, initialize the Matter.js modules and create the base environment:

const { Engine, Render, Runner, Bodies, Composite, Constraint } = Matter;

const engine = Engine.create();
const world = engine.world;

// Disable world gravity for pure ballistic evaluation, or leave standard gravity
engine.gravity.y = 0;

const render = Render.create({
    element: document.body,
    engine: engine,
    options: {
        width: 800,
        height: 400,
        wireframes: false
    }
});

Render.run(render);
Runner.run(Runner.create(), engine);

Creating the Spring-Loaded System

Model the head as a static body, the tongue tip as a small dynamic circle, and define the spring:

// Base anchor (chameleon's mouth)
const base = Bodies.rectangle(150, 200, 40, 40, { isStatic: true });

// Tongue tip projectile
const tongueTip = Bodies.circle(160, 200, 10, {
    density: 0.005,      // Low mass increases muzzle velocity
    frictionAir: 0.001   // Low air resistance for long reach
});

// Elastomeric spring (stores tension)
// Placed far behind the base to represent internal tension
const elasticSpring = Constraint.create({
    bodyA: base,
    bodyB: tongueTip,
    length: 10,          // Target contracted rest length
    stiffness: 0.15,     // High stiffness represents coiled collagen sheaths
    render: { strokeStyle: '#e74c3c', lineWidth: 3 }
});

// Latch: holds the projectile pulled back before release
const latch = Constraint.create({
    bodyA: base,
    bodyB: tongueTip,
    pointB: { x: 0, y: 0 },
    length: 20,
    stiffness: 1.0,
    render: { strokeStyle: '#333333', lineWidth: 4 }
});

Composite.add(world, [base, tongueTip, elasticSpring, latch]);

Executing the Catapult Release

To mimic the biological trigger, stretch the spring and then sever the latch. Pull the tongue tip backward, set its equilibrium target far forward, and release the latch constraint:

function loadAndFire() {
    // 1. Cocking phase: displace the tongue tip backward behind the anchor
    Matter.Body.setPosition(tongueTip, { x: 100, y: 200 });

    // 2. Set the spring anchor forward to establish projected direction
    elasticSpring.pointB = { x: 500, y: 0 }; 
    elasticSpring.length = 0; // Ideal zero-length spring for complete contraction

    // 3. Ballistic release: remove the latch constraint
    setTimeout(() => {
        Composite.remove(world, latch);
    }, 1000);
}

loadAndFire();

Directional Control and Damping

To keep the projection linear and prevent erratic oscillation upon full extension: