logo
AxisViewCamera

camera · physics-puzzle

AxisViewCamera

1
Unlock

Install with the CLI:

bjs download AxisViewCamera

AxisViewCamera

A drafting-table camera: a top view, a side view, and a swing between them.

What it does

The game has three dimensions and the mouse moves in two. Each view looks straight down one axis, so a drag in it moves things along exactly two world axes. The top view looks down −Y with +X to the right and −Z up the screen. The side view looks down −Z with +X to the right and +Y up. Both keep +X on the right, so between them every axis is in reach, and the swing is a quarter turn about X with nothing sliding sideways.

V swaps views, 1 picks the top view and 2 the side view.

The swing follows the arc around the field, not the straight line between the two resting spots. That line passes close to the centre, and the field would balloon halfway through. The camera turns its offset and its facing together and blends the distance, so the field stays framed the whole way round. Reverse mid-swing and the new swing starts from where the camera is.

It is a perspective camera with a narrow lens. Each view backs off until the near face of the play volume fills the window, checked against both its height and its width. The fit is redone every frame from the canvas's CSS size, so a resize never crops the field.

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.

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 AxisViewCamera
    bjs download AxisViewCamera

    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
{
  "World": {
    "tags": ["world"],
    "components": { "KeyboardInput": {} }
  },
  "Camera": {
    "tags": ["camera"],
    "components": {
      "AxisViewCamera": { "view": "top", "size": [72, 32, 32], "fov": 0.6 }
    }
  }
}

SpaceGolf's field is 72 by 32 by 32, centred on the origin. KeyboardInput turns key presses into the events the view keys arrive on.

Props

  • view (string, default 'top') — the view to start in, 'top' or 'side'.
  • center (vec3, default [0, 0, 0]) — centre of the play volume. The camera aims here.
  • size (vec3, default [64, 28, 28]) — full size of the volume on x, y and z.
  • fov (number, default 0.6) — vertical field of view in radians.
  • margin (number, default 1.06) — room around the volume. 1.06 leaves a 6% border; below 1 counts as 1.
  • transition (number, default 0.8) — seconds a swing takes. 0 cuts straight to the new view.
  • toggleKey (string, default 'KeyV') — key code that swaps views.
  • topKey (string, default 'Digit1') — key code for the top view.
  • sideKey (string, default 'Digit2') — key code for the side view.
  • near (number, default 0.5) — near clip plane.
  • far (number, default 4000) — far clip plane.
  • shake (number, default 0.6) — how hard a shake kicks the view. At full trauma it moves up to 0.9 world units per unit of shake. 0 ignores shakes.

Events

Emits:

  • camera.active.changed { entityId, handle } once, on the first frame. A pointer tool learns which camera to cast rays from here.
  • axisview.view.changed { entityId, view, previous } when a swing starts, and once on the first frame so a HUD can light the starting view.

Listens:

  • keyboard.keydown { code } for the three view keys.
  • axisview.view.set { view } and axisview.view.toggle do the same from a HUD. An unknown view is ignored.
  • cameraShake.impulse { impulse } adds trauma, which bleeds off at 1.8 per second.

Dependencies

None. The view keys arrive as keyboard.keydown, so something in the scene has to emit them.

Notes

  • One System drives one camera, made for the first entity that carries the component. Keep it the only camera component in the scene.
  • It runs before PointerDrag (priority 85 against 75), so rays come from this frame's pose. It keeps running while the world is paused.
  • A shake moves the camera in the screen plane and never turns it. A tilted view would shift the black holes under the pointer.
  • fov, near and far reach the camera once, when it is made. The fit reads fov every frame, so a fov changed at runtime moves the camera without changing the lens.
  • With no canvas, in a headless test, the fit assumes 16:9.

More like this

GravityLens
KeyboardInput
PointerDrag
SpaceGolfHUD
ArcCamera
BlackHole
CameraFollow
CameraState6DOF
CaptureZone
ChaseCamera6DOF
ChaseCameraTarget
GravityBody
GravityMass
MassDriver
MotionTrail
PinballCamera
ShooterCamera
SpaceGolfDirector
SpaceRock
Spin
TrajectoryPreview
WhiteHole
WorldOriginAnchor
Wormhole

Was this page helpful?

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

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search