Skip to main content
← All demos

Revolute Joint (Hinge)

game.ts
const renderLayers = {
foreground: 1 << 0,
};

export const createRevoluteJointGame = async (): Promise<Game> => {
const { game, world, renderContext, time } = createGame('demo-game');

createCamera(world, {
isStatic: true,
cullingMask: renderLayers.foreground,
verticalWorldUnits: DEMO_VERTICAL_WORLD_UNITS,
});

await createHinges(world, renderContext, renderLayers.foreground);

const collisionPairs: CollisionPair[] = [];
const collisionManifolds: CollisionManifold[] = [];
const contactConstraints: ContactConstraint[] = [];

// Gravity and pushes must run before collision/joint resolution, so this
// tick's forces are reflected in the velocities those solvers see; the
// revolute joint solver must run after collision resolution so the door's
// hinge gets the "last word" on velocity each tick.
world.addSystem(createGravityEcsSystem(time));
world.addSystem(createPushEcsSystem(time));
world.addSystem(createBroadPhaseEcsSystem(collisionPairs));
world.addSystem(
createNarrowPhaseEcsSystem(collisionPairs, collisionManifolds),
);
world.addSystem(
createCollisionResolutionEcsSystem(
collisionManifolds,
contactConstraints,
time,
),
);
world.addSystem(createRevoluteJointEcsSystem(time));
world.addSystem(createCameraEcsSystem(time));
world.addSystem(createRenderEcsSystem(renderContext));
world.addSystem(createEulerIntegrationEcsSystem(time));

return game;
};

This demo showcases RevoluteJoint in three different setups. On the left, a door is hinged to a wall mount, its swing limited to 90 degrees between closed and open; gravity swings it shut and a periodic push swings it back open. In the middle, a pendulum is hinged by an arm to a fixed pivot and, with no limit and no push at all, simply swings back and forth under gravity, rotation is completely free. On the right, a wheel is hinged directly to its hub and, having been given a single initial spin, keeps rotating indefinitely: unlike RevoluteJoint's translation lock, nothing resists rotation unless a limit is enabled. RevoluteJoint has no built-in motor, so the door's swing is driven by a small demo-only system that periodically applies an off-center impulse (see push.component.ts and push.system.ts).