logo
MouseHole

pinball

MouseHole

Talks toScore
1
Unlock

Install with the CLI:

bjs download MouseHole

MouseHole

A saucer / scoop that captures the ball, holds it briefly for a score award, then kicks it back into play.

What it does

A proximity check against the ball's XZ position triggers capture: the system emits mouseHole.captured and score.add (points to ownerEntity), then pins the ball to the hole with its velocity zeroed for holdSeconds. On release it applies kickoutVelocity via the physics body, emits mouseHole.released, and starts a short cooldown so the hole doesn't immediately re-capture the ball it just launched. The hole is a marker (typically a flat disc); the ball just needs a Physics body for the kickout to work.

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 MouseHole

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

    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 } }
    }
  },
  "Saucer": {
    "components": {
      "MeshPrimitive": {
        "primitive": "cylinder",
        "diameter": 1.2,
        "height": 0.3,
        "position": [0, 0.15, -4],
        "material": { "diffuseColor": [0.2, 0.2, 0.25] }
      },
      "MouseHole": {
        "points": 1000,
        "ownerEntity": "Player",
        "hitRadius": 0.5,
        "holdSeconds": 1.0,
        "kickoutVelocity": [0, 0, -12]
      }
    }
  }
}

Props

  • points (number, default 1000) — points awarded when the hole catches the ball.
  • ownerEntity (string, default 'Player') — score recipient.
  • hitRadius (number, default 0.5) — XZ capture radius.
  • holdSeconds (number, default 1.0) — seconds the ball is held before kickout.
  • kickoutVelocity ([vx, vy, vz], default [0, 0, -12]) — velocity the ball is launched with on release.

Events

  • emits mouseHole.captured — when the ball is caught; payload { holeId, entityId }.
  • emits score.add — alongside capture, crediting ownerEntity with points.
  • emits mouseHole.released — after holdSeconds, when the ball is kicked out; payload { holeId, entityId }.

Dependencies

MeshPrimitive — the hole's position and the ball mesh it pins/teleports. Score — receives the score.add event.

Notes

  • Only the first ball-tagged entity is captured.
  • While captured the ball's mesh is teleported to the hole at y 0.5 every frame; the kickout uses the renderer's physicsSetBodyVelocity, so the ball needs a Physics body.
  • A ~0.5s post-kickout cooldown blocks re-capture; capture/hold/cooldown state lives on the Component and round-trips through JSON.

More like this

MeshPrimitive
Score
BoatMode
BoatWater
Bumper
ContactDamage
ContactImpulse
Flipper
Obstacle
Physics
PinballBuilder
PinballBuilderInput
PinballCamera
PinballLayout
PinballTable
Plunger
Spinner
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