logo
Spinner

pinball

Spinner

Talks toScore
1
Unlock

Install with the CLI:

bjs download Spinner

Spinner

A freely-spinning bar that the ball spins on contact, scoring once per full revolution.

What it does

When a ball passes within hitRadius the system imparts angular velocity to the bar (direction set by which side of it the ball crossed), then integrates that spin each frame with drag decaying it toward zero. It's purely kinematic — the bar's MeshPrimitive is rotated directly around Y rather than using a Havok hinge (Havok JS doesn't expose hinge constraints cleanly). Every completed revolution emits spinner.spun and score.add for pointsPerSpin to ownerEntity, so one strong hit keeps scoring as the bar coasts.

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 Spinner

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

    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
{
  "ScoreState": {
    "components": {
      "Score": { "defaultPoints": 100, "scores": { "Player": 0 } }
    }
  },
  "Spinner": {
    "components": {
      "MeshPrimitive": {
        "primitive": "box",
        "width": 1.4,
        "height": 0.8,
        "depth": 0.08,
        "position": [0, 0.6, -3],
        "material": { "diffuseColor": [0.9, 0.9, 0.5] }
      },
      "Spinner": {
        "pointsPerSpin": 100,
        "ownerEntity": "Player",
        "hitRadius": 0.9,
        "drag": 2.0
      }
    }
  }
}

Props

  • pointsPerSpin (number, default 100) — points per full revolution.
  • ownerEntity (string, default 'Player') — score recipient.
  • hitRadius (number, default 0.9) — XZ distance at which the ball spins the bar.
  • drag (number, default 2.0) — angular drag per second; higher stops it faster.
  • startAngle (number, default 0) — initial bar Y rotation in radians.

Events

  • emits spinner.spun — on each completed revolution; payload { spinnerId, revolutions, points }.
  • emits score.add — alongside, crediting ownerEntity with revolutions * pointsPerSpin.

Dependencies

MeshPrimitive — the bar mesh it rotates and the ball position it reads. Score — receives the score.add event.

Notes

  • Only the first ball-tagged entity is used for the contact check.
  • Score fires per accumulated revolution, so a single hard hit can award several point chunks while the bar spins down.
  • Angular velocity, current angle, and accumulated spin live on the Component and serialize cleanly.

More like this

MeshPrimitive
Score
BoatMode
BoatWater
Bumper
ContactDamage
ContactImpulse
Flipper
MouseHole
Obstacle
Physics
PinballBuilder
PinballBuilderInput
PinballCamera
PinballLayout
PinballTable
Plunger
SurfacePatch
Velocity6DOF

Was this page helpful?

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

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search