logo
CaptureZone

gameplay · physics-puzzle

CaptureZone

1
Unlock

Install with the CLI:

bjs download CaptureZone

CaptureZone

A sphere that takes whatever tagged thing flies into it. In Space Golf it is the mineral plant.

What it does

Each frame the zone checks every live entity tagged acceptTag against its radius, measured from its own MeshPrimitive position. A hit emits capturezone.captured with the zone's points, takes the entity out of play (parked if it came from a pool, destroyed if not) and swells the zone's mesh in a short pulse so the catch is seen.

Candidates are found by tag, not by a component query, so one zone catches a GravityBody rock, a physics ball or a walking crate. Parked pool slots keep their tags, so the zone skips anything inactive. It skips pool blueprints too, since a blueprint carries the tags of its copies.

Once a frame is enough even for a fast rock, because GravityBody never lets one slip through between looks. After each of its fixed 1/120 s steps it checks every zone with this component's zoneAt, and stops a body on the step it comes in. The zone then finds the rock where it arrived, on the step the aim line showed, so a black hole parked on the zone's edge cannot swallow a rock the line showed caught.

With release off the entity stays in play, and is caught once each time it enters rather than on every frame it stays inside.

An optional engine plugin draws the zone's true reach: a soft glow with a crisp rim at exactly radius, on a quad that always faces the camera. A sphere looks like a disc from every side, so the one glow shows the right reach in a top view, a side view and every angle between. It flares on each catch.

Setup

The engine work ships with the component, in adapter/register.ts. A project made with bjs create installs it for you: src/main.ts calls every adapter/register.ts that bjs download puts in the project, before the scene loads. If you boot the game from your own code, call it once, right after building the adapter:

TypeScript
import { registerCaptureZoneExtension } from './Components/CaptureZone/adapter/register';

const adapter = new BabylonAdapter();
registerCaptureZoneExtension(adapter);
const game = new ArcadeGame(adapter, { … });

Without it zones catch exactly the same but show no glow, and the System warns once. The plugin is for BabylonAdapter only; with any other adapter the call does nothing.

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

    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
{
  "Plant": {
    "tags": ["plant"],
    "components": {
      "MeshPrimitive": {
        "primitive": "torus",
        "diameter": 4.6,
        "thickness": 0.5,
        "tessellation": 48,
        "position": [27, 0, 7]
      },
      "CaptureZone": { "radius": 2.5, "acceptTag": "rock", "points": 100 }
    }
  }
}

Anything tagged rock with a MeshPrimitive is a candidate. In Space Golf the plant is a pool blueprint that the director moves for each level.

Props

  • radius (number, default 2) — reach from the zone's MeshPrimitive position. The rim counts as inside.
  • acceptTag (string, default "rock") — only entities with this tag are caught.
  • points (number, default 100) — passed along on the event for whoever keeps score. The zone scores nothing itself.
  • release (boolean, default true) — take the catch out of play. Off, it stays in play and is caught once per entry.
  • pulse (number, default 0.35) — how much the mesh swells on a catch, as a fraction of its size. It eases back over 0.35 s. 0 turns it off.
  • color ([r, g, b], default [0.3, 1, 0.6]) — colour of the plugin's glow.

Events

Emits:

  • capturezone.captured — { zoneId, entityId, points, x, y, z }, the point being where the entity was caught. A released catch is already out of play when listeners hear about it.

Listens to nothing.

Dependencies

Notes

  • Where zones overlap, a target is taken once, by the first zone to see it. A zone never takes itself, even when it carries the tag it accepts.
  • With release off, a GravityBody still stops for the rest of the frame it comes in on, then flies on from inside.
  • The pulse writes the zone mesh's scale and always comes to rest at exactly 1. Size the mesh through MeshPrimitive, not by scaling it from elsewhere.
  • The glow is sized when it is first attached. Changing radius in play moves the catch but not the glow.
  • Catching needs no renderer, so a headless world scores the same.

More like this

MeshPrimitive
SpaceGolfDirector
AxisViewCamera
BallPossession
BallReset
BlackHole
DirectionalLight
Enemy
EnvironmentTexture
Flash
Goal
GravityBody
GravityLens
GravityMass
HemisphericLight
LensFlare
MassDriver
Mesh
MoneyField
MotionTrail
NebulaSky
PointerDrag
Renderable
RespawnTimer
RoadTreadmill
RoundReset
Scoreboard
Shadow
ShipDamageFX
Skybox
SmokeScreen
SoccerDirector
SpaceDust
SpaceGolfHUD
SpaceRock
SpaceShooterFX
Spin
ToneMapping
TrajectoryPreview
WeaponsVan
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