69 lines
2.7 KiB
JavaScript
69 lines
2.7 KiB
JavaScript
// Menu music spans Intro -> MainMenu -> LevelSelect as one continuous bed
|
|
// (Phaser's sound manager lives on the game, not the scene, so a Sound
|
|
// object started in one scene keeps playing through scene.start() calls
|
|
// into the next). Only ONE menu track is active at a time:
|
|
// - the main title theme (DEFAULT_KEY) - the default, and what Intro /
|
|
// MainMenu always play;
|
|
// - a campaign's own theme, if the campaign defines one (musicKey, see
|
|
// data/levels/index.js) - LevelSelect switches to it while that
|
|
// campaign's map is showing (campaign 2 -> urban-trap-theme) and back
|
|
// to the main title for campaigns without one.
|
|
// playMenuTrack swaps the active track (stopping the old one); it resumes
|
|
// rather than restarts a track that's already active but paused, and no-ops
|
|
// if it's already playing. playMenuMusic is the default (main title)
|
|
// shorthand the menu scenes call from create().
|
|
const DEFAULT_KEY = 'main_title_music';
|
|
|
|
// The track currently active across the menu scenes (or null if none).
|
|
let activeKey = null;
|
|
|
|
/**
|
|
* Makes `key` the active menu track (stopping the current one if it's a
|
|
* different key), or resumes it if it's already active but paused. `key`
|
|
* defaults to the main title theme, so `playMenuTrack(scene, undefined)`
|
|
* and `playMenuMusic(scene)` are equivalent. A key that never loaded
|
|
* (missing file / load failure) silently falls back to the main title -
|
|
* the same load-tolerant pattern as voiceLine.js.
|
|
*/
|
|
export function playMenuTrack(scene, key = DEFAULT_KEY) {
|
|
if (!scene.cache.audio.exists(key)) key = DEFAULT_KEY;
|
|
|
|
if (activeKey === key) {
|
|
// Already the active track: keep it - resume if it was stopped (e.g. by
|
|
// PlayScene), no-op if it's still playing.
|
|
const existing = scene.sound.get(key);
|
|
if (!existing) {
|
|
scene.sound.add(key, { loop: true, volume: 0.5 }).play();
|
|
return;
|
|
}
|
|
if (!existing.isPlaying) existing.play();
|
|
return;
|
|
}
|
|
|
|
// Swap: stop the current track, then start (or resume) the new one.
|
|
if (activeKey) scene.sound.get(activeKey)?.stop();
|
|
activeKey = key;
|
|
|
|
const existing = scene.sound.get(key);
|
|
if (existing) {
|
|
existing.play();
|
|
return;
|
|
}
|
|
scene.sound.add(key, { loop: true, volume: 0.5 }).play();
|
|
}
|
|
|
|
// Intro / MainMenu always want the main title theme.
|
|
export function playMenuMusic(scene) {
|
|
playMenuTrack(scene, DEFAULT_KEY);
|
|
}
|
|
|
|
// PlayScene calls this when gameplay starts: stop WHATEVER menu track is
|
|
// active (main title or a campaign theme) and clear the active pointer, so
|
|
// the next menu scene's play* call starts its track fresh.
|
|
export function stopMenuMusic(scene) {
|
|
if (!activeKey) return;
|
|
const key = activeKey;
|
|
activeKey = null;
|
|
scene.sound.get(key)?.stop();
|
|
}
|