Low-Friction Air Hockey Puck in Matter.js
This guide explains how to simulate an air hockey puck gliding seamlessly over an invisible low-friction air cushion in Matter.js. By fine-tuning physical properties such as surface friction, static friction, air resistance, and restitution, you can accurately emulate the near-frictionless hover generated by real air table jets without needing complex force fields or custom particle systems.
Core Physics Properties in Matter.js
To create the illusion of an air cushion, you must eliminate standard surface-to-surface resistance while carefully controlling atmospheric drag. Matter.js provides four essential body properties to achieve this:
friction: Determines sliding friction when touching other bodies. Set this to0to remove contact drag.frictionStatic: Defines the force threshold required to initiate movement from a dead stop. Set this to0so the puck immediately responds to touches.frictionAir: Simulates ambient air resistance. In a real air table, air friction still exists. Setting this to0allows infinite travel, whereas a value between0.0005and0.002mimics realistic gliding deceleration.restitution: Controls elasticity during collisions. Setting this to0.98to1.0ensures the puck bounces off boundaries and mallets with minimal kinetic energy loss.
Implementation Example
The following code creates an engine, the boundary walls representing the table rink, and a circular puck tuned for frictionless movement:
const { Engine, Render, Runner, Bodies, Composite } = Matter;
const engine = Engine.create();
engine.gravity.y = 0; // Top-down 2D view: disable vertical gravity
const render = Render.create({
element: document.body,
engine: engine,
options: {
width: 800,
height: 600,
wireframes: false
}
});
// Create table walls with high elasticity and zero friction
const wallOptions = { isStatic: true, friction: 0, restitution: 1.0 };
const walls = [
Bodies.rectangle(400, 0, 800, 20, wallOptions),
Bodies.rectangle(400, 600, 800, 20, wallOptions),
Bodies.rectangle(0, 300, 20, 600, wallOptions),
Bodies.rectangle(800, 300, 20, 600, wallOptions)
];
// Create the air hockey puck
const puck = Bodies.circle(400, 300, 25, {
density: 0.001,
friction: 0,
frictionStatic: 0,
frictionAir: 0.001, // Subtle drag to replicate real-world air damping
restitution: 0.99, // Retain momentum on ricochet
render: {
fillStyle: '#ff2d55'
}
});
Composite.add(engine.world, [...walls, puck]);
Render.run(render);
Runner.run(Runner.create(), engine);Addressing High-Speed Tunneling
Because the puck moves at high velocities with negligible friction, it risks passing through walls—a common physics engine issue known as tunneling. Mitigate this by applying two configurations:
- Increase Engine Iterations: Increase
engine.positionIterationsandengine.velocityIterationsto at least8or10to improve collision resolution accuracy per frame. - Increase Wall Thickness: Build boundary walls with greater depth (e.g., 50 to 100 pixels wide) positioned outside the visible canvas area rather than thin barriers.