- name
- melonjs-events
- description
- Use this skill for the melonJS event bus and lifecycle hooks — subscribing to engine events, the per-frame and per-state event names, renderable lifecycle callbacks, and how to unsubscribe without leaking. Triggers on: event.on, event.off, event.once, event.emit, GAME_UPDATE, GAME_BEFORE_DRAW, LEVEL_LOADED, LOADER_COMPLETE, STATE_CHANGE, CANVAS_ONRESIZE, POINTERMOVE, WORLD_STEP, onActivateEvent, onDeactivateEvent, onDestroyEvent, lifecycle, subscribe, listener.
- license
- MIT
Events and lifecycle
The bus
import { event } from "melonjs";
const onUpdate = () => { /* … */ };
const unsubscribe = event.on(event.GAME_UPDATE, onUpdate); // on() returns its own off()
event.once(event.LEVEL_LOADED, () => { /* … */ });
// two ways to undo it — the same reference, or the returned function
event.off(event.GAME_UPDATE, onUpdate);
unsubscribe();
event.on/once/off/has all take an optional third context argument,
invoked as the handler's this. off matches on the pair — handler identity
AND context identity. on(EVT, fn, this) followed by off(EVT, fn) removes
nothing, silently.
Store the handler reference, or use the context argument. An inline arrow or
a fresh .bind(this) in the on call can never be removed — that is the
standard way to leak listeners in melonJS.
// ✗ unremovable
event.on(event.GAME_UPDATE, this.tick.bind(this));
// ✓ keep the bound reference
this._tick = this.tick.bind(this);
event.on(event.GAME_UPDATE, this._tick);
// later: event.off(event.GAME_UPDATE, this._tick);
// ✓ or skip the bind entirely — the context is part of the identity
event.on(event.GAME_UPDATE, this.tick, this);
// later: event.off(event.GAME_UPDATE, this.tick, this);
Custom event names work at runtime (event.emit("my.custom.event", payload)),
but on/emit are typed against a closed map of the engine's own events, so in
TypeScript a name outside that map is a compile error. Use your own emitter for
game events in a .ts project.
The events worth knowing
Per frame