logo
FirstPersonCamera

core

FirstPersonCamera

Free

Install with the CLI:

bjs download FirstPersonCamera

FirstPersonCamera

A walk-around camera at eye height: W/S walk, A/D turn, Q/E strafe.

What it does

FirstPersonCameraSystem creates a perspective camera through the renderer adapter and poses it every frame from keyboard input. The camera stays at eyeHeight above the floor. Every step goes through a pure sweep in FirstPersonCamera.core.ts that tests the player's body circle against the scene's Obstacle footprints, so the player slides along a cabinet instead of walking through it. Optional bounds keep the player inside a room.

Other components can ask it to walk somewhere with firstpersoncamera.goto. It walks there at its own pace and emits firstpersoncamera.arrived when it gets there. Any movement key cancels the walk. With persistKey set, the pose is saved to localStorage and restored on reload.

Use it in a scene

A scene is just data — a list of entities, each with its components. At startup the SceneLoader turns this JSON into a live world; edit the file and reload to rebuild it.

Fastest path

bjs download scene FirstPersonCamera

Pulls this exact scene into your project and runs it — no copy-paste. Add --all to grab the components and assets it needs too.

Or build it from scratch with the bjs CLI:

  1. 1Scaffold a project
    npm create @babylonjsmarket/arcade@latest my-game

    World, renderer, and dev server — ready to run.

  2. 2Install dependencies
    cd my-game && npm install
  3. 3Add FirstPersonCamera
    bjs download FirstPersonCamera

    Copies its source into src/ so the scene resolves.

    First time? Run bjs login once.

  4. 4Paste the scene into src/scenes/arcade-room.ts and run
    npm run dev

    SceneLoader builds the world from the JSON; reload to rebuild.

JSON
{
  "entities": {
    "Player": {
      "tags": ["player"],
      "components": {
        "FirstPersonCamera": {
          "position": [0, 6],
          "yaw": 3.1416,
          "eyeHeight": 1.7,
          "moveSpeed": 4,
          "bounds": { "minX": -9, "maxX": 9, "minZ": -9, "maxZ": 9 }
        }
      }
    },
    "Pillar": {
      "components": {
        "MeshPrimitive": {
          "primitive": "box",
          "width": 1,
          "height": 2,
          "depth": 1,
          "position": [0, 1, 0]
        },
        "Obstacle": { "halfWidth": 0.5, "halfDepth": 0.5 }
      }
    }
  }
}

Props

  • eyeHeight (metres, ~1.7) — camera height above the floor.
  • position ([x, z]) — start spot on the floor.
  • yaw (radians) — start facing; 0 looks toward +Z.
  • moveSpeed (units/s), turnSpeed (rad/s) — walk and turn rates.
  • approachDuration (seconds, 0.7) — how long a goto walk takes.
  • fov, near, far — the lens.
  • bounds ({ minX, maxX, minZ, maxZ }, optional) — the room's walls.
  • collide (boolean, default true) — slide against Obstacle footprints.
  • radius (metres, default 0.45) — the player's body radius for that collision.
  • persistKey (string, optional) — localStorage key for saving the pose.

Events

  • emits firstpersoncamera.created { entityId, handle } — the camera exists; Sound and CabinetLink use the handle.
  • emits firstpersoncamera.arrived { entityId, x, z, yaw, cancelled } — a goto walk finished or was cancelled.
  • listens firstpersoncamera.goto { x, z, yaw? } — walk to a spot.
  • listens keyboard.keydown / keyboard.keyup — movement keys.

Dependencies

Obstacle — for the walk collision.

More like this

Was this page helpful?

We read every note — tell us what's working and what isn't.

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search