logo
PinballWall

pinball

PinballWall

1
Unlock

Install with the CLI:

bjs download PinballWall

PinballWall

Walls from a list of points.

What it does

A pinball table is mostly walls, and almost none of them are square to the table. Guide rails lean in toward the flippers. The top is a round arch. Typing a centre, a length and an angle for every box is how tables end up with gaps.

PinballWall takes the path instead. Give it points, or an arc, and on its first frame it lays one box along each piece. Each box is a child entity named <id>_0, <id>_1 and so on, with a MeshPrimitive to see, a static Physics body to bounce off and a Shadow.

Each box is one wall thickness longer than the gap it covers. Cut exactly to length, two boxes at a bend leave a notch on the outside corner, and the ball finds it. With the extra length they overlap. On a 0.4 wall each box is 0.4 longer than its gap, so at a square corner each one runs half that past the joint.

Remove the wall entity and its boxes go with it.

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

    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
{
  "Wall_Left": {
    "components": {
      "PinballWall": {
        "points": [[-8, 39], [-8, -31]]
      }
    }
  },
  "Wall_Arch": {
    "components": {
      "PinballWall": {
        "arc": {
          "center": [0, -31],
          "radius": 8,
          "from": 180,
          "to": 0,
          "segments": 16
        }
      }
    }
  },
  "Island": {
    "components": {
      "PinballWall": {
        "points": [[2, 0], [5, 0], [3.5, -3]],
        "closed": true,
        "height": 1,
        "thickness": 0.3
      }
    }
  }
}

Points are [x, z] on the playfield. Arc angles are degrees: 0° points along +X and 90° points up the table (-Z), so an arch over the top runs from 180 to 0.

Props

  • points ([x, z][], default []). The path, point to point. Ignored when arc is set.
  • arc ({ center, radius, from, to, segments? }, default none). Draw along part of a circle instead. segments defaults to 8; more is rounder.
  • closed (boolean, default false). Join the last point back to the first.
  • height (number, default 1.6). Wall height.
  • thickness (number, default 0.4). Wall thickness, and how much each box overlaps the next.
  • y (number, default 0). Height of the wall's base.
  • color ([r, g, b], default [0.32, 0.18, 0.5]).
  • restitution (number, default 0.5). Bounce, 0 to 1.
  • friction (number, default 0.05).
  • castShadow (boolean, default true).

Events

None. It builds boxes and says nothing.

Dependencies

MeshPrimitive, Physics and Shadow. Each box carries one of each, so those systems must be in the scene.

Rebuilding a wall

  • The boxes are built once. Changing points on a running wall does nothing; remove it and add a new one.
  • The geometry is in PinballWall.core.ts: arcPoints turns an arc into points, and wallPieces turns points into boxes.

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