Skip to content

Signal

Inspired by Godot's signals, signals are a lightweight pub/sub mechanism for communication between behaviors.

Declaring a signal

ts
import {
  Behavior,
  SignalEvent
} from "@jolly-pixel/engine";

export class PlayerBehavior extends Behavior {
  onPlayerPunch = new SignalEvent();

  update() {
    if (this.actor.world.input.isMouseButtonDown("left")) {
      this.onPlayerPunch.emit();
    }
  }
}

Listening to a signal

Other behaviors can subscribe to a signal with connect and unsubscribe with disconnect:

ts
const player = actor.getComponent(PlayerBehavior)!;

player.onPlayerPunch.connect(() => {
  console.log("Player punched!");
});

SignalEvent API

ts
interface SignalEvent<T extends unknown[] = []> {
  // Notify all connected listeners
  emit(...args: T): void;

  // Subscribe a listener
  connect(listener: SignalListener<T>): void;

  // Unsubscribe a listener
  disconnect(listener: SignalListener<T>): void;

  // Remove all listeners
  clear(): void;
}

type SignalListener<T extends unknown[]> = (...args: T[]) => void;

Typed signals

SignalEvent accepts a generic tuple to type the emitted arguments:

ts
onDamage = new SignalEvent<[amount: number, source: string]>();

// Emit with typed arguments
this.onDamage.emit(10, "fireball");

// Listener receives typed parameters
behavior.onDamage.connect((amount, source) => {
  console.log(`Took ${amount} damage from ${source}`);
});

See also