Fix music.mp3 not playing — add preload, canplaythrough retry, unblock on first user interaction

This commit is contained in:
justin committed 2026-05-14 13:04:44 -07:00
1 parent b03bd6fb27
commit 25204998db
1 file changed
+27 -4
+27 -4
View File
@@ -56,12 +56,18 @@ function clearSave() { try { localStorage.removeItem(SAVE_KEY); } catch(_){} }
const Music = (() => { const Music = (() => {
let audio = null; let audio = null;
let muted = false; let muted = false;
let wantPlay = false; /* true if we tried to play but were blocked */
function getAudio() { function getAudio() {
if (!audio) { if (!audio) {
audio = new Audio('./music.mp3'); audio = new Audio('./music.mp3');
audio.loop = true; audio.loop = true;
audio.volume = 0.5; audio.volume = 0.5;
audio.preload = 'auto';
/* If audio loads and we wanted to play, try again */
audio.addEventListener('canplaythrough', () => {
if (wantPlay && !muted) audio.play().catch(() => {});
});
} }
return audio; return audio;
} }
@@ -76,11 +82,17 @@ const Music = (() => {
return { return {
play() { play() {
if (muted) return; if (muted) return;
wantPlay = true;
const a = getAudio(); const a = getAudio();
if (a.paused) a.play().catch(() => {}); if (a.readyState >= 3) {
/* Enough data to play */
if (a.paused) a.play().catch((e) => { console.warn('Music play blocked:', e); });
}
/* else: canplaythrough listener will fire and retry */
}, },
pause() { pause() {
if (audio) audio.pause(); wantPlay = false;
if (audio && !audio.paused) audio.pause();
}, },
toggle() { toggle() {
muted = !muted; muted = !muted;
@@ -88,6 +100,13 @@ const Music = (() => {
if (muted) Music.pause(); if (muted) Music.pause();
else Music.play(); else Music.play();
}, },
/* Call once on first user interaction to unblock autoplay */
unblock() {
const a = getAudio();
if (wantPlay && !muted && a.paused) {
a.play().catch(() => {});
}
},
}; };
})(); })();
@@ -584,7 +603,11 @@ class Game {
this.show('title'); this.show('title');
SFX.boot(); SFX.boot();
this._showController(false); this._showController(false);
const go = () => { document.getElementById('screen-title').removeEventListener('click',go); this.showContinueOrName(); }; const go = () => {
document.getElementById('screen-title').removeEventListener('click', go);
Music.unblock();
this.showContinueOrName();
};
document.getElementById('screen-title').addEventListener('click', go); document.getElementById('screen-title').addEventListener('click', go);
} }
@@ -598,7 +621,7 @@ class Game {
document.getElementById('save-prog-disp').textContent = `Q${save.currentQ}/100 (${pct}%)`; document.getElementById('save-prog-disp').textContent = `Q${save.currentQ}/100 (${pct}%)`;
document.getElementById('save-score-disp').textContent = save.score.toLocaleString(); document.getElementById('save-score-disp').textContent = save.score.toLocaleString();
document.getElementById('btn-continue-save').onclick = () => this.restoreFromSave(save); document.getElementById('btn-continue-save').onclick = () => { Music.unblock(); this.restoreFromSave(save); };
document.getElementById('btn-new-game').onclick = () => { document.getElementById('btn-new-game').onclick = () => {
document.getElementById('continue-warn').textContent = 'Starting a new game will erase your saved progress!'; document.getElementById('continue-warn').textContent = 'Starting a new game will erase your saved progress!';
document.getElementById('btn-new-game').textContent = '✦ CONFIRM NEW GAME'; document.getElementById('btn-new-game').textContent = '✦ CONFIRM NEW GAME';