logo
DropTarget

pinball

DropTarget

1
Unlock

Install with the CLI:

bjs download DropTarget

DropTarget

Targets that fall when hit, in banks.

What it does

A drop target is a box the ball bounces off. Hit it and it falls into the playfield. Knock down the whole row and the row pays a bonus, then stands back up.

When a ball comes within hitRadius of a standing target:

  • The mesh sinks dropDepth into the playfield.
  • Its physics body is destroyed, so the ball rolls over the spot. Hiding the mesh alone would leave an invisible wall.
  • It says dropTarget.down and pays points.

Targets with the same bank name are one bank. When the last one drops, it says dropTarget.bankComplete and pays bankPoints. resetDelay seconds later the bank stands back up and says dropTarget.reset.

A target only rises once the ball is at least clearance away. A box that rises through the ball puts a solid where the ball already is, and the physics engine throws the ball out at once in whatever direction the overlap points. So a target under the ball waits, and its neighbours rise without 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 DropTarget
    bjs download DropTarget

    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
{
  "Drop_1": {
    "components": {
      "MeshPrimitive": {
        "primitive": "box",
        "width": 1.3,
        "height": 1,
        "depth": 0.35,
        "position": [-2.6, 0.5, 15.5],
        "material": {
          "diffuseColor": [1, 0.8, 0.3],
          "emissiveColor": [0.45, 0.3, 0.05]
        }
      },
      "Physics": {
        "shapeType": "box",
        "motionType": "static",
        "restitution": 0.4,
        "friction": 0.05
      },
      "DropTarget": {
        "bank": "center",
        "points": 500,
        "bankPoints": 5000,
        "hitRadius": 0.95
      }
    }
  }
}

Add Drop_2 and Drop_3 the same way with the same bank, a little further along x.

Props

  • bank (string, default "bank"). Targets with the same name drop and reset together.
  • points (number, default 500). Paid for each target.
  • bankPoints (number, default 5000). Paid for the whole bank.
  • ownerEntity (string, default "Player"). Who gets the points.
  • hitRadius (number, default 1). Distance on the table (x, z) from the target's centre that knocks it down.
  • resetDelay (seconds, default 2.5). Wait after the bank is down before it stands up. 0 waits for dropTarget.resetRequest.
  • dropDepth (number, default 1.3). How far it sinks.
  • clearance (number, default 1.6). How far the ball must be before a target rises.

Events

Emits:

  • dropTarget.down, { entityId, bank, points, remaining }. remaining is how many still stand.
  • dropTarget.bankComplete, { bank, count }.
  • dropTarget.reset, { bank }.
  • score.add, { ownerEntity, points }, once per target and once for the bank.

Listens to:

  • dropTarget.resetRequest, { bank? }. Stand a bank up now. No bank means every bank. Send it at the start of a new game.

Dependencies

MeshPrimitive on the same entity, and a static Physics body for the ball to hit. Score to count the points. The ball needs the ball tag.

The bank maths

  • The bookkeeping is in DropTarget.core.ts: createBank, knockDown and canRaise.
  • A target that is already down is never knocked down again, so a bank completes once per reset.

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