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:
- An anchor point (chameleon head).
- A projectile body (tongue tip).
- A primary elastomeric spring constraint with high stiffness.
- A temporary latch constraint to hold the spring in tension.
- 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:
- Linear Rails: Constrain the tongue tip to an
invisible sensor track or set
tongueTip.axesto restrict angular drift. - Energy Dissipation (Over-extension): Once the
tongue reaches peak extension, immediately reduce the spring's stiffness
or replace it with a low-stiffness tether constraint using an
afterUpdateevent loop. This simulates the physiological arrest of the tongue before retractive muscle engagement.