Skip to content

Make a swinging door ​

For a kit door in one level entry, use HingedDoor with swingDegrees: pick the right door.

Goal ​

Walk into a hinged door to push it open. Press F to drive it to 85 degrees, then press F again to close it.

Files you will edit ​

  • src/prefabs.ts
  • src/game.ts

Steps ​

  1. In the third-person template, append this prefab to src/prefabs.ts, using its existing prefab import. It has no Door or Interactable tag, so the template's key-door system will not teleport it. Its default layer meets the hero's existing mask. Keep the slab clear of walls throughout its sweep.

    ts
    export const SwingDoorPrefab = prefab({
      name: 'swing-door',
      body: {
        shape: 'box',
        dims: [0.6, 1, 0.08],
        kind: 'dynamic',
        mass: 15,
        layer: { defaultLayer: true },
        mask: { player: true, staticGeometry: true },
      },
    });
  2. In src/game.ts, add physics to the existing SDK import (public games import from gameable), and SwingDoorPrefab to the ./prefabs import. Add this state and system above defineGame. The options are reused rather than allocated in the system.

    ts
    let swingJoint = 0;
    let swingOpen = false;
    const swingMotor = { mode: 'position', target: 0, maxForce: 500 } as const;
    const swingTarget = { ...swingMotor, target: 0 };
    
    function driveSwingDoor(ctx: GameContext): void {
      if (!ctx.input.pressed('F')) return;
      swingOpen = !swingOpen;
      swingTarget.target = swingOpen ? 85 : 0;
      physics.setMotor(swingJoint, swingTarget);
    }
  3. Append these statements to the existing init(ctx) after paintTheLevel. The hinge is on the slab's left edge, just above the floor. Motors start off, so walking into the slab pushes it freely until the first F press.

    ts
    const swingDoor = ctx.spawn(SwingDoorPrefab, { x: 0.6, y: 1.1, z: -3 });
    tint(swingDoor, DOOR_COLOUR);
    swingOpen = false;
    swingJoint = physics.hinge(swingDoor, 0, {
      anchor: { x: 0, y: 1.1, z: -3 },
      axis: { x: 0, y: 1, z: 0 },
      minDeg: -90,
      maxDeg: 90,
      friction: 1,
    });
  4. Add driveSwingDoor to the existing systems array after locomotionSystem. Positive angles follow the right-hand rule about +Y: the door moves relative to the world (b = 0). Position targets and limits use degrees. The explicit 500 N·m limit exceeds the default 100 N·m; once engaged, the motor holds the requested angle. To restore free pushing, send mode: 'off' with a target of zero.

Verify ​

sh
npm run dev

Walk to the slab at (0.6, 1.1, -3) and push it from either side: it swings but stops at ±90 degrees. Press F: it settles near +85 degrees; press F again: it returns near zero. Temporarily inspect physics.jointValue(swingJoint) in the system to check those angles; the result is degrees, not radians.

See also ​