Skip to content

Commit 2bab855

Browse files
committed
Fix sound effects - improve AudioContext initialization and update service worker cache
1 parent fcf6410 commit 2bab855

2 files changed

Lines changed: 42 additions & 21 deletions

File tree

script.js

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,24 @@ let touchStartX = 0;
2020
let touchStartY = 0;
2121
let minSwipeDistance = 50; // Minimum distance for swipe gesture
2222

23-
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
23+
// Initialize AudioContext - will be created after user interaction
24+
let audioContext = null;
2425

25-
// Add a click listener to resume audio context
26-
document.body.addEventListener('click', () => {
26+
// Function to initialize/resume audio context
27+
const initAudioContext = () => {
28+
if (!audioContext) {
29+
audioContext = new (window.AudioContext || window.webkitAudioContext)();
30+
}
2731
if (audioContext.state === 'suspended') {
2832
audioContext.resume();
2933
}
30-
});
34+
return audioContext;
35+
};
36+
37+
// Add multiple event listeners to resume audio context (required by browsers)
38+
document.addEventListener('click', initAudioContext, { once: false });
39+
document.addEventListener('touchstart', initAudioContext, { once: false });
40+
document.addEventListener('keydown', initAudioContext, { once: false });
3141

3242
// Haptic feedback function
3343
const hapticFeedback = (type = 'light') => {
@@ -133,24 +143,35 @@ gameBoard.addEventListener('touchend', handleTouchEnd, { passive: false });
133143

134144
// Create longer, more arcade-style sound effects
135145
const playSound = (type) => {
136-
if (!audioContext || audioContext.state === 'suspended') return;
146+
// Initialize audio context if needed
147+
const ctx = initAudioContext();
148+
if (!ctx || ctx.state === 'suspended') {
149+
// Try to resume if suspended
150+
if (ctx && ctx.state === 'suspended') {
151+
ctx.resume().catch(() => {
152+
// If resume fails, audio won't play - that's okay
153+
return;
154+
});
155+
}
156+
return;
157+
}
137158

138-
const now = audioContext.currentTime;
159+
const now = ctx.currentTime;
139160
const duration = type === 'win' ? 1.2 : type === 'lose' ? 1.0 : type === 'draw' ? 0.8 : 0.3;
140161

141162
switch (type) {
142163
case 'move':
143164
// Bouncy arcade beep for moves
144-
const osc1 = audioContext.createOscillator();
145-
const gain1 = audioContext.createGain();
165+
const osc1 = ctx.createOscillator();
166+
const gain1 = ctx.createGain();
146167
osc1.type = 'square';
147168
osc1.frequency.setValueAtTime(400, now);
148169
osc1.frequency.exponentialRampToValueAtTime(600, now + 0.15);
149170
osc1.frequency.exponentialRampToValueAtTime(300, now + 0.3);
150171
gain1.gain.setValueAtTime(0.3, now);
151172
gain1.gain.exponentialRampToValueAtTime(0.01, now + duration);
152173
osc1.connect(gain1);
153-
gain1.connect(audioContext.destination);
174+
gain1.connect(ctx.destination);
154175
osc1.start(now);
155176
osc1.stop(now + duration);
156177
break;
@@ -159,15 +180,15 @@ const playSound = (type) => {
159180
// Victory fanfare - ascending chord sequence
160181
const notes = [523.25, 659.25, 783.99, 1046.50]; // C5, E5, G5, C6
161182
notes.forEach((freq, i) => {
162-
const osc = audioContext.createOscillator();
163-
const gain = audioContext.createGain();
183+
const osc = ctx.createOscillator();
184+
const gain = ctx.createGain();
164185
osc.type = 'sine';
165186
osc.frequency.setValueAtTime(freq, now);
166187
gain.gain.setValueAtTime(0, now + i * 0.15);
167188
gain.gain.linearRampToValueAtTime(0.4, now + i * 0.15 + 0.05);
168189
gain.gain.exponentialRampToValueAtTime(0.01, now + duration - i * 0.1);
169190
osc.connect(gain);
170-
gain.connect(audioContext.destination);
191+
gain.connect(ctx.destination);
171192
osc.start(now + i * 0.15);
172193
osc.stop(now + duration);
173194
});
@@ -177,15 +198,15 @@ const playSound = (type) => {
177198
// Defeat sound - descending notes
178199
const loseNotes = [523.25, 440, 349.23, 261.63]; // C5, A4, F4, C4
179200
loseNotes.forEach((freq, i) => {
180-
const osc = audioContext.createOscillator();
181-
const gain = audioContext.createGain();
201+
const osc = ctx.createOscillator();
202+
const gain = ctx.createGain();
182203
osc.type = 'sawtooth';
183204
osc.frequency.setValueAtTime(freq, now);
184205
gain.gain.setValueAtTime(0, now + i * 0.2);
185206
gain.gain.linearRampToValueAtTime(0.35, now + i * 0.2 + 0.05);
186207
gain.gain.exponentialRampToValueAtTime(0.01, now + i * 0.2 + 0.25);
187208
osc.connect(gain);
188-
gain.connect(audioContext.destination);
209+
gain.connect(ctx.destination);
189210
osc.start(now + i * 0.2);
190211
osc.stop(now + i * 0.2 + 0.3);
191212
});
@@ -194,24 +215,24 @@ const playSound = (type) => {
194215
case 'draw':
195216
// Neutral draw sound - two tones
196217
[440, 523.25].forEach((freq, i) => {
197-
const osc = audioContext.createOscillator();
198-
const gain = audioContext.createGain();
218+
const osc = ctx.createOscillator();
219+
const gain = ctx.createGain();
199220
osc.type = 'triangle';
200221
osc.frequency.setValueAtTime(freq, now + i * 0.2);
201222
gain.gain.setValueAtTime(0, now + i * 0.2);
202223
gain.gain.linearRampToValueAtTime(0.3, now + i * 0.2 + 0.05);
203224
gain.gain.exponentialRampToValueAtTime(0.01, now + i * 0.2 + 0.35);
204225
osc.connect(gain);
205-
gain.connect(audioContext.destination);
226+
gain.connect(ctx.destination);
206227
osc.start(now + i * 0.2);
207228
osc.stop(now + i * 0.2 + 0.4);
208229
});
209230
break;
210231

211232
case 'restart':
212233
// Quick restart beep
213-
const osc2 = audioContext.createOscillator();
214-
const gain2 = audioContext.createGain();
234+
const osc2 = ctx.createOscillator();
235+
const gain2 = ctx.createGain();
215236
osc2.type = 'square';
216237
osc2.frequency.setValueAtTime(600, now);
217238
osc2.frequency.exponentialRampToValueAtTime(800, now + 0.15);

service-worker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const CACHE_NAME = 'tic-tac-toe-v1';
1+
const CACHE_NAME = 'tic-tac-toe-v2';
22
const urlsToCache = [
33
'/',
44
'/index.html',

0 commit comments

Comments
 (0)