logo
PinballScrollCamera

pinball

PinballScrollCamera

1
Unlock

Install with the CLI:

bjs download PinballScrollCamera

PinballScrollCamera

A camera for a pinball table too tall to fit on one screen.

What it does

Alien Crush and Devil's Crush had tables two or three screens tall. The camera showed one screen at a time and slid to the next when the ball got there. This does the same.

It cuts the table into screens equal pieces, with screen 0 at the bottom where the flippers are. Pinball Tower is 78 deep in 3 screens, so each screen is 26: screen 0 runs from z 13 to 39, screen 1 from -13 to 13, screen 2 from -39 to -13.

It fits the camera distance to one screen, not the whole table. With a 0.9 radian field of view, 26 of table needs the camera 13 / tan(0.45) = 26.9 back, times marginFactor for room round the edge.

The camera keeps its screen until the ball is more than hysteresis past the edge. With 1.5, a ball must reach z 11.5 to leave screen 0 for screen 1, and z 14.5 to come back. Without that gap, a ball resting on the line, say on a pair of flippers, flips the view every time it wobbles.

It glides to the new screen at a rate that does not depend on the frame rate. One 1/30 second frame and two 1/60 second frames land on the same spot.

When the ball is parked off the table (below y -5, between balls or after the game) the camera stays where it is.

It sits beside an ArcCamera and moves it by writing its targetOffset z and its distance. It says pinballScrollCamera.screenChanged when the screen changes, so a HUD can show which screen you are on.

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

    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
{
  "Table": {
    "components": {
      "PinballTable": { "width": 16, "depth": 78 }
    }
  },
  "Camera": {
    "components": {
      "ArcCamera": {
        "restTarget": "Playfield",
        "follow": false,
        "controlsEnabled": false,
        "alpha": 1.5708,
        "beta": 0.5
      },
      "PinballScrollCamera": {
        "mode": "screens",
        "screens": 3,
        "fov": 0.9,
        "marginFactor": 1.3,
        "aim": 1.5
      }
    }
  }
}

The ArcCamera must look at the middle of the table (restTarget on the playfield) with follow off.

Props

  • followTag (string, default "ball"). Tag of the entity to watch.
  • mode ("screens" or "follow", default "screens"). One screen at a time, or keep the ball near the middle.
  • screens (number, default 3). How many screens tall the table is.
  • hysteresis (number, default 1.5). How far past a screen's edge the ball must go to change screen.
  • ease (number, default 5). How fast the camera catches up, per second.
  • lead (number, default 2). Follow mode: look this far up the table from the ball.
  • aim (number, default 0). Screens mode: look this far down the table (+Z) from each screen's middle. A tilted camera sees more table above the middle of the picture than below it, so a little aim keeps the bottom of each screen in view.
  • fov (number, default 0.9). Vertical field of view, radians.
  • marginFactor (number, default 1.15). Room round one screen when fitting the distance.
  • lockControls (boolean, default true). Turn off the mouse orbit.

Events

Emits:

  • pinballScrollCamera.screenChanged, { screen, count }. The camera moved to another screen.

Listens to:

  • pinballTable.resized. The table's depth.

Dependencies

Notes

  • In follow mode the view stops at each end of the table, so it never shows past the top or bottom edge.
  • With no PinballTable at all, it takes the depth as 33.2.

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