This guide demonstrates how to create a "pop-in" plugin that listens for game events and triggers audio, maintaining strict separation of concerns.
The core engine does not contain a "play sound" function inside the combat logic. Instead, the combat logic emits an event. The Audio Plugin sits in the background, listening for that specific event, and plays the sound when it hears it.
// plugins/AudioPlugin.js
export const AudioPlugin = {
id: 'audio-system',
// The engine calls this upon loading the plugin
init(eventBus, assetManager) {
this.eventBus = eventBus;
this.assetManager = assetManager;
// Listen for global game events
this.eventBus.on('ENTITY_DIED', (data) => {
this.playSound('explosion_01.mp3');
});
this.eventBus.on('PLAYER_JUMP', () => {
this.playSound('jump_sfx.ogg');
});
},
playSound(fileName) {
// Access pre-loaded audio buffers from the asset manager
const sound = this.assetManager.getAudio(fileName);
sound.play();
}
};
Because the plugin follows a standard interface (the init function), the core engine's loader handles it automatically:
// Core Engine Loader
async function loadPlugins() {
const pluginFiles = ['plugins/AudioPlugin.js', 'plugins/RendererPlugin.js'];
for (const path of pluginFiles) {
const { plugin } = await import(path);
// Inject the Event Bus so the plugin can "talk" to the rest of the game
plugin.init(globalEventBus, globalAssetManager);
}
}
AudioPlugin.js, the combat system continues to function perfectly without errors.ENTITY_DIED event from the browser console.