Repository navigation
Events
There are two event classes with different rules. Mixing them up is the most common mistake.
RewardSystem (an EventEmitter) |
kernel EventBus
|
|
|---|---|---|
| Subscribe | on(event, callback) |
on(event, callback, priority) |
on returns |
a function that unsubscribes | the bus, for chaining |
| Unsubscribe | call the returned function, or off
|
off(event, callback) |
| One-shot | none | once(event, callback) |
| Order | insertion order | higher priority first |
Event names are lowercase strings. EventBus.Events.LEVEL_UP is a constant whose value is 'level_up'. Listening for 'LEVEL_UP' never fires.
A listener that throws is logged and does not stop the other listeners. This holds for both classes.
const stop = rewards.on('level_up', ({ oldLevel, newLevel, totalXP }) => {});
stop();| Event | Payload | When |
|---|---|---|
xp_gained |
{ amount, reason, leveledUp, newLevel, total } |
after every addXP, including the XP from games and achievements |
level_up |
{ oldLevel, newLevel, totalXP } |
after xp_gained, when the level rose |
achievement_unlocked |
the achievement definition plus id
|
when an achievement unlocks |
new_high_score |
{ gameName, score } |
when recordGame beats the stored high score |
streak_updated |
{ current, longest } |
when the calendar day changes, in init() or recordGame()
|
save_failed |
{ key } |
when a storage write fails |
amount in xp_gained is what changed. A removal larger than the player's XP reports the XP that was there.
const onTick = ({ dt }) => {};
kernel.events.on('tick', onTick, 10);
kernel.events.off('tick', onTick);Keep the callback in a variable. off needs the same function, and it removes every registration of it.
| Event | Payload | When |
|---|---|---|
tick |
{ dt } |
start of each frame |
fixed_update |
{ dt } |
each fixed step, before systems run fixedUpdate
|
render |
{ dt } |
end of each frame |
kernel_started |
none | kernel.start() |
kernel_stopped |
none | kernel.stop() |
system_registered |
{ name, system } |
systems.register |
system_unregistered |
{ name } |
systems.unregister |
plugin_loaded |
{ name, version } |
a plugin's init finished |
plugin_unloaded |
{ name } |
plugins.remove |
collision_enter |
{ a, b } |
two colliders start to overlap (2.4.0) |
collision_exit |
{ a, b } |
they stop overlapping, or one of them is removed (2.4.0) |
dt is in seconds and capped at 0.1.
a and b are the two colliders, typed as CollisionEvent. Each event fires once per overlap. Components still get onCollisionEnter on every step while the pair overlaps. See Engine.
Other EventBus methods: emit(event, data), clear(event?), hasListeners(event).
Plugins listen on the kernel bus. To let them see reward events, hand the bus to the reward system.
import { Game, RewardSystem, DataService } from 'dopaminejs';
const game = new Game();
const rewards = new RewardSystem(new DataService(), { events: game.kernel.events });
// or: { kernel: game.kernel }Each reward event is then emitted on both. rewards.on(...) keeps working as before.
Plugin: Ecosystem needs this bridge. Without it BattlePassPlugin and LeaderboardPlugin hear nothing.
Start
Progression
Engine
Packages
Reference