logo
MassDriver

physics · physics-puzzle

MassDriver

1
Unlock

Install with the CLI:

bjs download MassDriver

MassDriver

A launcher that fires pooled bodies on a timer. In Space Golf it is the rock chute.

What it does

Every interval seconds the driver takes a body from its pool, puts it muzzleOffset ahead of itself and sends it along direction at speed. It never creates a body: world.acquire(pool, { x, y, z }) hands back a parked slot already placed at the muzzle, and the driver only sets that body's GravityBody velocity. A full pool recycles its oldest body. A pool name with nothing registered under it fires nothing and emits massdriver.jammed.

Each shot is tilted inside a cone of half-angle spread, so the stream fans out a little and a perfect line through a gap is not a perfect answer. The tilt comes from a small seeded generator whose state lives with the driver and restarts from seed each time the driver enters play. A level fires the same stream every time it loads, and two drivers with one seed fire the same shots.

The clock expects a player to change it. Change interval mid-wait and the wait already running is scaled by the same ratio, so "slower" lands on the next rock, not one whole old interval later. A long frame fires once rather than a backlog of missed shots. Switching active back on restarts the clock at firstDelay.

Nothing in it is golf. A mortar or a waterfall of crates is the same component with other numbers.

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

    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
{
  "Rocks": {
    "tags": ["rock"],
    "components": {
      "Pool": { "name": "rock", "size": 24 },
      "MeshPrimitive": { "primitive": "sphere", "diameter": 1, "segments": 8 },
      "GravityBody": { "radius": 0.42, "maxSpeed": 45 }
    }
  },
  "Chute": {
    "components": {
      "MeshPrimitive": {
        "primitive": "cylinder",
        "height": 3,
        "diameterTop": 1.3,
        "diameterBottom": 2,
        "position": [-30, 0, -8]
      },
      "MassDriver": {
        "pool": "rock",
        "direction": [1, 0, 0],
        "speed": 11,
        "interval": 2.2,
        "muzzleOffset": 2,
        "spread": 0.012
      }
    }
  }
}

The rock blueprint needs a GravityBody for the shot to move. In Space Golf the chute is a pool blueprint too, with active: false and firstDelay: 0. The director places it for each level and switches it on at GO, so the first rock leaves on that frame.

Props

  • pool (string, default "rock") — the pool bodies are taken from.
  • interval (number, default 2.4) — seconds between automatic shots.
  • speed (number, default 10) — launch speed in units per second.
  • direction ([x, y, z], default [1, 0, 0]) — launch direction, any length. Zero or NaN falls back to +X.
  • muzzleOffset (number, default 1.6) — how far ahead of the driver, along direction, a body appears.
  • spread (number, default 0.015) — half-angle of the launch cone in radians. 0 fires dead straight.
  • active (boolean, default true) — fire on the timer.
  • firstDelay (number, default 0.6) — seconds before the first shot after the driver enters play or is switched on.
  • seed (number, default 0x5eed) — seeds the spread.

Events

Emits:

  • massdriver.launched — a body left the muzzle: { driverId, entityId, x, y, z, vx, vy, vz }.
  • massdriver.jammed — there was no pool to take from: { driverId, pool }.

Listens:

  • massdriver.fire — fire once now, timer or not: { driverId? }. Leave out the id to fire every driver.
  • massdriver.active.set — start or stop the timer: { driverId?, active }. A bare payload means on.

Dependencies

  • MeshPrimitive — the driver's position, and the barrel it turns.
  • GravityBody — on the pooled bodies. The driver sets its velocity.

Notes

  • The driver owns its mesh's rotation. It turns local +Y, the long axis of a cylinder or capsule, onto direction, and replaces any rotation you author.
  • It runs before GravityBody, so a rock fired this frame also moves this frame.
  • An inactive driver still answers massdriver.fire. A parked driver, or a pool blueprint, answers nothing.
  • A body with no GravityBody still appears at the muzzle, and massdriver.launched still carries the velocity, so another mover can pick it up.

More like this

GravityBody
MeshPrimitive
SpaceGolfDirector
AsteroidField
AxisViewCamera
BlackHole
BoatMode
BoatWater
Bumper
CaptureZone
ContactDamage
ContactImpulse
DeckDealer
EnemySpawner
GravityLens
GravityMass
MotionTrail
MouseHole
Obstacle
ObstacleField
Physics
PointerDrag
RoadSpawner
SpaceGolfHUD
SpaceRock
Spin
Spinner
SurfacePatch
TrajectoryPreview
Velocity6DOF
WhiteHole
Wormhole

Was this page helpful?

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

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search