Skip to content

Commit 0d07685

Browse files
committed
Fix cutscene skip and enter flow
1 parent 1b205d2 commit 0d07685

1 file changed

Lines changed: 91 additions & 53 deletions

File tree

js/app.js

Lines changed: 91 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
let phase = 'phase1';
5151
let cutsceneDone = false;
5252
let cutsceneSkipBound = false;
53+
let phase3ReadyToEnter = false;
5354

5455
function playVideo(video) {
5556
video.currentTime = 0;
@@ -59,10 +60,23 @@
5960
console.warn('[Cutscene] Video playback failed:', error);
6061
});
6162
}
63+
return promise;
64+
}
65+
66+
function setPrompt(message) {
67+
if (!pressPrompt) return;
68+
pressPrompt.textContent = message;
69+
pressPrompt.style.display = 'block';
70+
pressPrompt.style.opacity = 1;
71+
}
72+
73+
function hidePrompt() {
74+
if (!pressPrompt) return;
75+
pressPrompt.style.opacity = 0;
6276
}
6377

6478
function show(to, from) {
65-
playVideo(to);
79+
const playPromise = playVideo(to);
6680
requestAnimationFrame(() => {
6781
to.style.opacity = '1';
6882
if (from) {
@@ -71,71 +85,34 @@
7185
}, { once: true });
7286
}
7387
});
88+
return playPromise;
7489
}
7590

7691
function goToPhase3() {
7792
if (phase === 'phase3' || phase === 'done') return;
7893
const from = phase === 'loop' ? v2 : v1;
7994
phase = 'phase3';
95+
phase3ReadyToEnter = false;
8096
v2.loop = false;
8197
v2.pause();
82-
if (pressPrompt) pressPrompt.style.opacity = 0;
83-
unbindCutsceneSkip();
84-
show(v3, from);
85-
}
86-
87-
function onCutsceneSkipInput(e) {
88-
if (phase === 'phase3' || phase === 'done') return;
89-
if (e.type === 'keydown' && e.code !== 'Space' && e.code !== 'Enter') return;
90-
if (e.type !== 'keydown' && !isTouchDevice) return;
91-
if (e.cancelable) e.preventDefault();
92-
goToPhase3();
93-
}
94-
95-
function bindCutsceneSkip() {
96-
if (cutsceneSkipBound) return;
97-
cutsceneSkipBound = true;
98-
window.addEventListener('keydown', onCutsceneSkipInput);
99-
window.addEventListener('touchstart', onCutsceneSkipInput, { passive: false });
100-
}
101-
102-
function unbindCutsceneSkip() {
103-
if (!cutsceneSkipBound) return;
104-
cutsceneSkipBound = false;
105-
window.removeEventListener('keydown', onCutsceneSkipInput);
106-
window.removeEventListener('touchstart', onCutsceneSkipInput);
107-
}
108-
109-
v1.addEventListener('ended', () => {
110-
if (phase !== 'phase1') return;
111-
phase = 'loop';
112-
show(v2, v1);
113-
setTimeout(() => {
114-
if (pressPrompt) {
115-
pressPrompt.style.display = 'block';
116-
pressPrompt.textContent = 'PRESS SPACE / TAP TO CONTINUE';
117-
}
118-
}, 4000);
119-
}, { once: true });
120-
121-
bindCutsceneSkip();
122-
123-
// jabardasti yahan bhi saare flags
124-
v1.muted = true;
125-
v1.defaultMuted = true;
126-
v1.playsInline = true;
127-
if (v1.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) {
128-
playVideo(v1);
129-
} else {
130-
v1.addEventListener('canplay', () => playVideo(v1), { once: true });
98+
hidePrompt();
99+
const playPromise = show(v3, from);
100+
if (playPromise && typeof playPromise.catch === 'function') {
101+
playPromise.catch(() => {
102+
phase = 'awaiting-entry';
103+
phase3ReadyToEnter = true;
104+
setPrompt('PRESS SPACE / TAP TO ENTER');
105+
});
106+
}
131107
}
132108

133-
// phase3 - go to website
134-
v3.addEventListener('ended', () => {
109+
function enterWebsite() {
135110
if (cutsceneDone) return;
136111
cutsceneDone = true;
137112
phase = 'done';
113+
phase3ReadyToEnter = false;
138114
unbindCutsceneSkip();
115+
hidePrompt();
139116

140117
website.classList.add('visible');
141118

@@ -155,7 +132,7 @@
155132
else { Audio.stopAmbient(); }
156133
});
157134
}
158-
135+
159136
// paint website first, then crossfade cinematic out
160137
requestAnimationFrame(() => {
161138
requestAnimationFrame(() => {
@@ -180,7 +157,68 @@
180157
});
181158
});
182159
});
160+
}
161+
162+
function onCutsceneSkipInput(e) {
163+
if (e.type === 'keydown' && e.code !== 'Space' && e.code !== 'Enter') return;
164+
if (e.type !== 'keydown' && !isTouchDevice) return;
165+
if (e.cancelable) e.preventDefault();
166+
if (phase === 'phase1' || phase === 'loop') {
167+
goToPhase3();
168+
return;
169+
}
170+
if (phase === 'awaiting-entry' && phase3ReadyToEnter) {
171+
enterWebsite();
172+
}
173+
}
174+
175+
function bindCutsceneSkip() {
176+
if (cutsceneSkipBound) return;
177+
cutsceneSkipBound = true;
178+
window.addEventListener('keydown', onCutsceneSkipInput);
179+
window.addEventListener('touchstart', onCutsceneSkipInput, { passive: false });
180+
}
181+
182+
function unbindCutsceneSkip() {
183+
if (!cutsceneSkipBound) return;
184+
cutsceneSkipBound = false;
185+
window.removeEventListener('keydown', onCutsceneSkipInput);
186+
window.removeEventListener('touchstart', onCutsceneSkipInput);
187+
}
188+
189+
v1.addEventListener('ended', () => {
190+
if (phase !== 'phase1') return;
191+
phase = 'loop';
192+
show(v2, v1);
193+
setTimeout(() => {
194+
setPrompt('PRESS SPACE / TAP TO SKIP');
195+
}, 4000);
196+
}, { once: true });
197+
198+
bindCutsceneSkip();
183199

200+
// jabardasti yahan bhi saare flags
201+
v1.muted = true;
202+
v1.defaultMuted = true;
203+
v1.playsInline = true;
204+
v2.muted = true;
205+
v2.defaultMuted = true;
206+
v2.playsInline = true;
207+
v3.muted = true;
208+
v3.defaultMuted = true;
209+
v3.playsInline = true;
210+
if (v1.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) {
211+
playVideo(v1);
212+
} else {
213+
v1.addEventListener('canplay', () => playVideo(v1), { once: true });
214+
}
215+
216+
// phase3 - wait for explicit enter input
217+
v3.addEventListener('ended', () => {
218+
if (cutsceneDone) return;
219+
phase = 'awaiting-entry';
220+
phase3ReadyToEnter = true;
221+
setPrompt('PRESS SPACE / TAP TO ENTER');
184222
}, { once: true });
185223

186224
});

0 commit comments

Comments
 (0)