How to Simulate Earthquake Shaking in Matter.js
This guide explains how to model seismic ground motion and analyze its structural impact on multi-story building frames using the Matter.js 2D physics engine. By constructing flexible structural frames with rigid bodies and elastic constraints, anchoring them to a movable base, and driving that base with oscillating or accelerogram-based motion, you can effectively reproduce earthquake dynamics, resonance, and structural failure in a browser environment.
1. Setting Up the Environment
Begin by initializing the fundamental Matter.js modules:
Engine, Render, Runner,
Bodies, Composite, Constraint,
and Events. Disable or tune default gravity to match your
simulation's scale, typically leaving standard gravity along the Y-axis
(engine.gravity.y = 1).
const { Engine, Render, Runner, Bodies, Composite, Constraint, Body, Events } = Matter;
const engine = Engine.create();
const world = engine.world;
const render = Render.create({
element: document.body,
engine: engine,
options: { width: 800, height: 600, wireframes: false }
});
Render.run(render);
Runner.run(Runner.create(), engine);2. Building the Multi-Story Frame
A realistic multi-story frame requires vertical columns, horizontal floor beams, and connections that provide both stiffness and damping.
- Base/Foundation: Create a single rectangular body representing the ground slab. Set its collision filter so it does not snag on the world boundaries.
- Floor Slabs and Columns: Model floors and columns
as distinct rectangular rigid bodies
(
Bodies.rectangle). - Joints (Constraints): Connect columns to floor
slabs using
Constraint.create. Setting astiffnessvalue slightly below1.0(e.g.,0.8to0.95) allows the frame to flex, storing and releasing elastic potential energy under dynamic load. Add multiple constraints per joint to resist rotational moments.
const groundBase = Bodies.rectangle(400, 550, 300, 20, { isKinematic: true });
Composite.add(world, groundBase);
// Example for one story:
const leftColumn = Bodies.rectangle(320, 490, 15, 100);
const rightColumn = Bodies.rectangle(480, 490, 15, 100);
const floorBeam = Bodies.rectangle(400, 430, 200, 20);
Composite.add(world, [leftColumn, rightColumn, floorBeam]);
// Anchor columns to base
const jointLeft = Constraint.create({
bodyA: groundBase,
pointA: { x: -80, y: -10 },
bodyB: leftColumn,
pointB: { x: 0, y: 50 },
stiffness: 0.9,
damping: 0.05
});
Composite.add(world, jointLeft);Stack these assemblies vertically to build additional stories, anchoring each floor's columns to the floor slab below.
3. Simulating Ground Motion
Earthquake excitation is simulated by manipulating the kinematic base
body before each physics engine step using the beforeUpdate
event.
Harmonic Ground Motion (Sinusoidal)
Harmonic motion allows you to test the building against resonant frequencies:
let time = 0;
const amplitude = 15; // Displacement in pixels
const frequency = 0.05; // Oscillation speed (rad/step)
const baseY = 550;
const baseX = 400;
Events.on(engine, 'beforeUpdate', () => {
time += 1;
// Calculate new position
const targetX = baseX + amplitude * Math.sin(time * frequency);
// Set position and velocity for accurate momentum transfer
const vx = amplitude * frequency * Math.cos(time * frequency);
Body.setVelocity(groundBase, { x: vx, y: 0 });
Body.setPosition(groundBase, { x: targetX, y: baseY });
});Accelerogram/Random Motion
For realistic earthquakes, import historical seismic data (time vs. acceleration) or generate filtered white noise. Calculate instantaneous velocity \(v(t) = v(t-1) + a(t) \cdot \Delta t\) and position \(x(t) = x(t-1) + v(t) \cdot \Delta t\), then update the base body accordingly.
4. Modeling Structural Failure
To simulate structural collapse:
- Stress Monitoring: On each engine tick, calculate the distance between the anchor points of each constraint.
- Breakable Joints: If the constraint length exceeds
a defined strain threshold, remove the constraint from the world using
Composite.remove(world, constraint).
Events.on(engine, 'afterUpdate', () => {
const allConstraints = Composite.allConstraints(world);
const maxStrain = 15; // Maximum allowable elongation in pixels
allConstraints.forEach(c => {
if (!c.bodyA || !c.bodyB) return;
const posA = Vector.add(c.bodyA.position, c.pointA);
const posB = Vector.add(c.bodyB.position, c.pointB);
const currentLength = Vector.magnitude(Vector.sub(posA, posB));
if (Math.abs(currentLength - c.length) > maxStrain) {
Composite.remove(world, c);
}
});
});5. Tuning Physics Parameters
- Constraint Damping: Real structures dissipate
energy. Increase
damping(between0.01and0.1) on constraints to avoid infinite oscillation. - Engine Iterations: In high-frequency simulations,
increase
engine.positionIterationsandengine.velocityIterations(default is 6 and 4; increase to 10 or 12) to prevent constraint drift and numerical instability during violent shaking.