How to Make Crumbling Floor Tiles in Matter.js
This article explains how to create interactive crumbling floor tiles using the Matter.js 2D physics engine. You will learn how to detect when a player stands on a tile, initiate a collapse countdown, convert the static tile into a dynamic falling body, and clean up the object once it leaves the simulation.
1. Define the Tile Body
In Matter.js, terrain is typically created with
isStatic: true so it resists gravity and collisions. To
make a tile crumble later, initialize it as a static body with custom
properties to track its trigger state and timer.
const { Bodies, Composite } = Matter;
function createCrumblingTile(x, y, width, height, dropDelay = 1000) {
const tile = Bodies.rectangle(x, y, width, height, {
isStatic: true,
label: 'crumblingTile',
render: {
fillStyle: '#c29a64'
}
});
// Custom metadata for tracking state
tile.dropDelay = dropDelay;
tile.isTriggered = false;
return tile;
}2. Detect Player Contact
Use Matter.js collision events to determine when the player lands on
top of the tile. Attach a listener to the collisionStart
event on your engine instance.
Matter.Events.on(engine, 'collisionStart', (event) => {
event.pairs.forEach((pair) => {
const { bodyA, bodyB } = pair;
const tile = [bodyA, bodyB].find(b => b.label === 'crumblingTile');
const player = [bodyA, bodyB].find(b => b.label === 'player');
if (tile && player && !tile.isTriggered) {
// Ensure the player is landing from above
if (player.position.y < tile.position.y) {
triggerTileCrumble(tile);
}
}
});
});3. Handle the Crumble and Drop Phase
Once triggered, lock the tile state so multiple collision events do
not restart the timer. When the designated duration expires, use
Matter.Body.setStatic(tile, false) to enable gravity,
causing the tile to fall away.
function triggerTileCrumble(tile) {
tile.isTriggered = true;
// Optional: visually indicate that the tile is about to fall
tile.render.fillStyle = '#8b5a2b';
setTimeout(() => {
// Make the tile dynamic so it falls
Matter.Body.setStatic(tile, false);
// Disable collision with the player after it starts falling (optional)
tile.collisionFilter.group = -1;
// Schedule cleanup
removeTileAfterDelay(tile, 3000);
}, tile.dropDelay);
}4. Remove the Tile from Memory
Dynamic bodies falling indefinitely will degrade performance. Once the tile has fallen off-screen, remove it from the Matter.js composite world.
function removeTileAfterDelay(tile, delay) {
setTimeout(() => {
Composite.remove(engine.world, tile);
}, delay);
}5. Optional: Adding a Shake Effect
To improve gameplay feedback, you can apply a subtle position offset
to the tile inside your main update loop while
tile.isTriggered is active and tile.isStatic
is still true.
Matter.Events.on(engine, 'beforeUpdate', () => {
engine.world.bodies.forEach((body) => {
if (body.label === 'crumblingTile' && body.isTriggered && body.isStatic) {
const shakeOffset = (Math.random() - 0.5) * 2;
Matter.Body.setPosition(body, {
x: body.position.x + shakeOffset,
y: body.position.y
});
}
});
});By coupling isStatic: true bodies with custom timers and
the setStatic method upon collision, you can implement
responsive crumbling platform mechanics suitable for 2D platformers and
puzzle games.