Skip to content

React when something enters a zone ​

Goal ​

Entering a sphere says “Inside”; leaving it says “Outside”, without a physics sensor.

Files you will edit ​

  • src/game.ts

Steps ​

  1. Add these declarations beside the imports in src/game.ts. Merge the gameable imports with the file's existing import.

    ts
    import { createTriggers, type GameContext } from 'gameable';
    
    const zoneHud = { message: 'Outside' };
    const zones = createTriggers({
      capacity: 1,
      watchCapacity: 1,
      onEnter() {
        zoneHud.message = 'Inside';
      },
      onExit() {
        zoneHud.message = 'Outside';
      },
    });
    let zone = 0;
    function resetZones(entity: number): void {
      zones.reset();
      zoneHud.message = 'Outside';
      zone = zones.addSphere(0, 0, 0, 3);
      zones.watch(entity);
    }
    function checkZones(ctx: GameContext): void {
      zones.step(ctx);
      zoneHud.message = zones.count(zone) > 0 ? 'Inside' : 'Outside';
      ctx.hud.set(zoneHud);
    }
  2. In init, call resetZones(hero) after top-down spawns its hero (use ctx.player in a template with a declarative player). Run checkZones(ctx) after movement and before the existing HUD write in update; remove that old HUD write for this exercise so it cannot overwrite the zone message. Alternatively put it in systems after movement systems. Merge zones.snapshot() / zones.restore(state) into the game's snapshot hooks.

  3. To despawn explicitly, call zones.unwatch(entity, ctx) before ctx.despawn(entity) if an immediate exit callback matters. These are inclusive point tests on Transform, not body overlap or swept tests; an entity without Transform is outside. All exits run before all enters.

Verify ​

sh
npm run dev

Move the hero within three metres of the origin: the HUD says Inside. Cross the sphere boundary: it says Outside. Stand still inside: the enter callback must not fire again. The result does not depend on physics contacts.

See also ​