Signals
Back to the reference

Signals

Named event channels, Godot-style, and the events an object sends up to whoever holds it.

13 symbols

createGameSignalfunctionnacatamalon

createGameSignal() => TGameSignal<T>

Makes a signal: a way for one part of the game to say "this happened" and for any other part to react, without the two knowing about each other.

A button does not need to know about the screen that lights up, and the screen does not need to know about the button: both know the signal. That is what keeps them apart, so either can be changed, removed or duplicated without touching the other.

Make it once, in a file of its own, and import it wherever it is needed. It belongs to the page, not to a game, so it can be fired from outside the canvas too (a web page button, a tool).

  • emit(value) tells everyone listening, straight away.
  • useSignal(signal, handler) listens from a scene, and stops by itself when the scene goes.
  • connect(handler) listens from anywhere else, and returns the function that stops.

A signal carries events, not state: nothing is kept after emit. What should still be true later (a score, a level reached) belongs in the game's state, not here.

Example

let score = 0;

// events.ts
export const coinCollected = createGameSignal<number>();

// coin.ts
coinCollected.emit(10);

// hud.ts, inside a scene
useSignal(coinCollected, (points) => { score += points; });
View source · signal/create_game_signal.ts:41

onEventfunctionnacatamalon

onEvent(object: TBox, name: string, handler: TObjectEventHandler<T>) => () => void

Listens to an event an object tells its parent: a button that was pressed, an enemy that died, a room whose coins are all gone.

The object's behaviours send it with useEvent, and it travels up from whatever sent it to the first object that listens, so listening on a whole thing hears what any part of it says. That is how a game hears a pack: listen on what createPack gave back (or pass on to createPack, which does this), even though the pack's content is only built when the pack lands.

  • It can be called at any moment, and it adds: two handlers on one event both run.
  • It stops by itself when the object goes away. The function it returns stops it earlier.
  • For something the whole game should hear, from anywhere, a signal (createGameSignal) is the tool. This is for one object telling the one above it.

Parameters

objectTBox

What to listen on: the event reaches it from itself or from anything inside it.

namestring

The event, as the behaviour sending it named it.

handlerTObjectEventHandler<T>

What to do, given what came with the event and the object that sent it.

Example

declare const enemy: TGameObject;
let score = 0;

onEvent<{ points: number }>(enemy, 'died', ({ points }) => {
    score += points;
});
View source · events/on_event.ts:38

scenePausedvariablenacatamalon

scenePaused: TGameSignal<TScenePauseEvent>

A scene has been paused: it stops updating but keeps being drawn.

The engine does not touch sound, timers or anything else when this happens, because what should stop is the game's decision: the music of a level usually carries on under its pause menu, its footsteps do not. This is how a game hears about it.

Fired only when it really changes: pausing a scene that is already paused says nothing.

Example

declare const steps: TSoundHandle;

useSignal(scenePaused, ({ scene }) => { if (scene === 'Level') steps.pause(); });
useSignal(sceneResumed, ({ scene }) => { if (scene === 'Level') steps.resume(); });
View source · signal/engine_signals.ts:45

useEventfunctionhooknacatamalon

useEvent(name: string) => (payload: T) => boolean

Declares an event this object can tell whoever holds it, and gives back the function that sends it.

Call it in a behaviour or a component body, where the object is being built; send it whenever you like, from a click, a key, a collision or a timer. It travels up the tree to the first object that listens (onEvent, or on in createPack) and stops there, so a pack's button can say it was pressed and the game that placed it hears it, and nothing above that.

The function answers whether anybody heard it, which a behaviour can use to do something by itself when nobody is listening.

Parameters

namestring

What the event is called. The one who listens uses the same name.

Example

registerScript('button', (self, props) => {
    const pressed = useEvent<{ label: string }>('pressed');
    listen(self, { onClick: () => pressed({ label: String(props.label) }) });
});
View source · hooks/events/use_event.ts:30

useSignalfunctionhooknacatamalon

useSignal(signal: TGameSignal<T>, handler: TSignalHandler<T>) => void

Listens to a signal from a scene, and stops listening by itself when that part of the scene goes away. Nothing to disconnect by hand.

Call it in the scene body, or in the body of something created with useSpawn: then it stops when that object is destroyed. It keeps listening while the scene is paused, because a signal is the game telling itself something, and a paused level may still need to hear it.

Parameters

signalTGameSignal<T>

The signal, made with createGameSignal.

handlerTSignalHandler<T>

What to do each time it fires. Receives what the signal carries.

Example

declare const coinCollected: TGameSignal<number>;

export const Hud: TSceneFn = () => {
    let score = 0;
    useSignal(coinCollected, (points) => { score += points; });
    return createScene();
};
View source · hooks/signal/use_signal.ts:30

TGameSignaltypenacatamalon

A channel one part of the game fires and any other part listens to, without either knowing the other exists. Made with createGameSignal.

Properties

emit
connect
sizenumber

How many are listening. Useful to spot a listener that was never disconnected.

View source · signal/types/t_game_signal.ts:18

TObjectEventHandlertypenacatamalon

TObjectEventHandler: (payload: T, from: TBox) => void

What a handler connected with onEvent is told: what came with the event, and the object that sent it (the button itself, inside the copy a game placed).

View source · events/object_events.ts:11

TScenePauseEventtypenacatamalon

What a scene pause signal carries: which scene it was.

Signals belong to the page, so with two games running at once both are heard here. The name is what tells them apart when that happens.

Properties

scenestring
View source · signal/engine_signals.ts:13