# Melonjs Events

Use this skill for the melonJS event bus and lifecycle hooks, subscribing to engine...

- Repository: https://github.com/melonjs/melonJS (6430 stars)
- Category: Engineering
- License: MIT
- Last updated: 2026-11-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add melonjs/melonJS --skill melonjs-events -g -a claude-code -y`
Codex: `npx skills add melonjs/melonJS --skill melonjs-events -g -a codex -y`
Cursor: `npx skills add melonjs/melonJS --skill melonjs-events -g -a cursor -y`
Gemini CLI: `npx skills add melonjs/melonJS --skill melonjs-events -g -a gemini-cli -y`
Claude Code plugin marketplace: `/plugin marketplace add melonjs/melonJS`

## 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.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Events and lifecycle

## The bus

```js
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.

```js
// ✗ 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**

| event | when |
|---|---|
| `GAME_BEFORE_UPDATE` / `GAME_UPDATE` / `GAME_AFTER_UPDATE` | around the world update, `GAME_UPDATE` is **not** emitted while paused |
| `GAME_BEFORE_DRAW` / `GAME_AFTER_DRAW` | around the draw pass |
| `WORLD_STEP` | after the physics step |
| `TICK` | the raw engine tick |

**Lifecycle**

The rest: https://github.com/melonjs/melonJS/blob/HEAD/packages/melonjs/skills/melonjs-events/SKILL.md
