S1 fix real: deblocare audio pe primul gest (acopera resume), nu doar btn-start
Fix-ul initial deblocà AudioContext-ul doar in handlerul btn-start. Lacuna: calea de resume (reload mid-campanie) intra direct pe harta fara btn-start -> ctx nedeblocat -> camere mute. Plus resume() singur nu ajunge pe iOS Safari. - unlockAudio() + listener global one-time (pointerdown+keydown capture): acopera fresh SI resume; buffer silentios iOS-safe. - beep() se auto-vindeca daca ctx redevine suspended. - Test smoke #9 rescris: headless creeaza ctx direct 'running' (ignora autoplay) -> vechiul "ctx running" trecea trivial. Acum: gest tastatura fara btn-start -> running (cale resume) + beep self-heal din ctx suspendat. - Demo campanie regenerat. Suita 24/24. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1878,6 +1878,7 @@ function doorHtml(style, isLast, isStuck){
|
||||
function beep(ok){
|
||||
try{
|
||||
var ctx=beep._ctx||(beep._ctx=new(window.AudioContext||window.webkitAudioContext)());
|
||||
if(ctx.state==='suspended') ctx.resume(); /* safety: ctx poate fi suspendat din nou */
|
||||
var t=ctx.currentTime; var fs=ok?[523,784]:[196];
|
||||
fs.forEach(function(f,k){
|
||||
var o=ctx.createOscillator(),g=ctx.createGain();
|
||||
@@ -1890,6 +1891,28 @@ function beep(ok){
|
||||
}catch(e){}
|
||||
}
|
||||
|
||||
/* ----- Deblocare audio (D2) — primul gest pe părinte creează+deblochează ctx-ul.
|
||||
Necesar pe TOATE căile, nu doar btn-start: la resume (reload mid-campanie) se intră
|
||||
direct pe hartă fără btn-start, iar camerele cheamă parent.beep() din iframe (gestul
|
||||
din iframe NU deblochează ctx-ul părintelui). Pe iOS Safari resume() singur nu ajunge
|
||||
→ redăm și un buffer silențios în gest. Listener one-time, se auto-elimină. */
|
||||
function unlockAudio(){
|
||||
try{
|
||||
var c=beep._ctx||(beep._ctx=new(window.AudioContext||window.webkitAudioContext)());
|
||||
if(c.state==='suspended') c.resume();
|
||||
var b=c.createBuffer(1,1,22050),s=c.createBufferSource();
|
||||
s.buffer=b; s.connect(c.destination); s.start(0);
|
||||
}catch(e){}
|
||||
}
|
||||
var _audioUnlocked=false;
|
||||
function _onFirstGesture(){
|
||||
if(_audioUnlocked) return; _audioUnlocked=true; unlockAudio();
|
||||
document.removeEventListener('pointerdown',_onFirstGesture,true);
|
||||
document.removeEventListener('keydown',_onFirstGesture,true);
|
||||
}
|
||||
document.addEventListener('pointerdown',_onFirstGesture,true);
|
||||
document.addEventListener('keydown',_onFirstGesture,true);
|
||||
|
||||
/* ----- parent.* API ----- */
|
||||
|
||||
window.nextRoom = function(data){
|
||||
@@ -2170,9 +2193,7 @@ document.getElementById('intro-title').textContent = MASTER.title;
|
||||
document.getElementById('intro-story').textContent = (MASTER.player?'Salut, '+MASTER.player+'! ':'')+MASTER.story;
|
||||
document.getElementById('intro-promise').textContent = N+' camere \\u00b7 ${nStyles} stiluri \\u00b7 1 cuvânt magic';
|
||||
document.getElementById('btn-start').onclick = function(){
|
||||
/* Deblochează AudioContext-ul AICI (gest direct pe părinte) — camerele cheamă
|
||||
parent.beep() din iframe, iar gestul din iframe NU deblochează ctx-ul părintelui. */
|
||||
try{ var c=beep._ctx||(beep._ctx=new(window.AudioContext||window.webkitAudioContext)()); if(c.state==='suspended') c.resume(); }catch(e){}
|
||||
unlockAudio(); /* gest direct pe părinte (handlerul global prinde și el, dar e idempotent) */
|
||||
clearProgress(); owResetPlayer(); showOverworld(0);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user