@onnie81/murdoku-spor 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/client/src/audio.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// copyright entanglements. Autoplay-safe: the context starts on first gesture.
|
|
4
4
|
|
|
5
5
|
let ctx = null;
|
|
6
|
-
let master, sfxBus, musicBus;
|
|
6
|
+
let master, sfxBus, musicBus, analyser;
|
|
7
7
|
let enabled = { sfx: true, music: true };
|
|
8
8
|
let musicOn = false;
|
|
9
9
|
let schedTimer = null;
|
|
@@ -16,6 +16,9 @@ function ensureCtx() {
|
|
|
16
16
|
master = ctx.createGain();
|
|
17
17
|
master.gain.value = 0.9;
|
|
18
18
|
master.connect(ctx.destination);
|
|
19
|
+
analyser = ctx.createAnalyser();
|
|
20
|
+
analyser.fftSize = 2048;
|
|
21
|
+
master.connect(analyser);
|
|
19
22
|
sfxBus = ctx.createGain();
|
|
20
23
|
sfxBus.gain.value = 0.5;
|
|
21
24
|
sfxBus.connect(master);
|
|
@@ -264,3 +267,21 @@ export function stopMusic() {
|
|
|
264
267
|
musicBus.gain.exponentialRampToValueAtTime(0.0001, ctx.currentTime + 0.8);
|
|
265
268
|
}
|
|
266
269
|
}
|
|
270
|
+
|
|
271
|
+
// diagnostics hook (used by the e2e test and handy in devtools)
|
|
272
|
+
if (typeof window !== 'undefined') {
|
|
273
|
+
window.__mdkAudio = {
|
|
274
|
+
state: () => (ctx ? ctx.state : 'none'),
|
|
275
|
+
musicOn: () => musicOn,
|
|
276
|
+
enabled: () => ({ ...enabled }),
|
|
277
|
+
rms() {
|
|
278
|
+
if (!analyser) return 0;
|
|
279
|
+
const a = new Float32Array(analyser.fftSize);
|
|
280
|
+
analyser.getFloatTimeDomainData(a);
|
|
281
|
+
let s = 0;
|
|
282
|
+
for (let i = 0; i < a.length; i++) s += a[i] * a[i];
|
|
283
|
+
return Math.sqrt(s / a.length);
|
|
284
|
+
},
|
|
285
|
+
ping: () => sfx('chime')
|
|
286
|
+
};
|
|
287
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React, { useEffect, useMemo, useRef, useState, useCallback } from 'react';
|
|
6
6
|
import { api } from '../api.js';
|
|
7
7
|
import { createGameStore, useGame } from '../game.js';
|
|
8
|
-
import { useApp, navigate, toast, getState } from '../store.js';
|
|
8
|
+
import { useApp, navigate, toast, getState, updateSettings } from '../store.js';
|
|
9
9
|
import { Board } from './Board.jsx';
|
|
10
10
|
import { Tray } from './Tray.jsx';
|
|
11
11
|
import { CluePanel } from './CluePanel.jsx';
|
|
@@ -44,10 +44,13 @@ export function PlayView({ gameId }) {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
function PlayInner({ loaded }) {
|
|
47
|
+
const app = useApp();
|
|
47
48
|
const store = useMemo(
|
|
48
49
|
() => createGameStore(loaded.game, loaded.puzzle, () => getState().settings, (key) => toast(t(key))),
|
|
49
50
|
[loaded]
|
|
50
51
|
);
|
|
52
|
+
const soundOn = app.settings.sfx !== false || app.settings.music !== false;
|
|
53
|
+
const soundToggle = () => updateSettings({ sfx: !soundOn, music: !soundOn });
|
|
51
54
|
const snap = useGame(store);
|
|
52
55
|
const boardRef = useRef(null);
|
|
53
56
|
const [drag, setDrag] = useState(null);
|
|
@@ -294,6 +297,7 @@ function PlayInner({ loaded }) {
|
|
|
294
297
|
<span className="stat-mist">✗ {snap.mistakes}</span>
|
|
295
298
|
</div>
|
|
296
299
|
<button className="icon-btn" onClick={() => setCaseOpen(true)} aria-label={t('caseFile')}>📜</button>
|
|
300
|
+
<button className="icon-btn" onClick={soundToggle} aria-label={t('sound')}>{soundOn ? '🔊' : '🔇'}</button>
|
|
297
301
|
{fsAvailable && (
|
|
298
302
|
<button className="icon-btn" onClick={fsToggle} aria-label={t('fullscreen')}>{isFs ? '🡼' : '⛶'}</button>
|
|
299
303
|
)}
|
|
@@ -358,6 +362,7 @@ function PlayInner({ loaded }) {
|
|
|
358
362
|
<span className="stat-time">{fmtTime(snap.timeMs)}</span>
|
|
359
363
|
<span className="stat-mist" title={t('mistakes')}>✗ {snap.mistakes}</span>
|
|
360
364
|
</div>
|
|
365
|
+
<button className="icon-btn" onClick={soundToggle} aria-label={t('sound')}>{soundOn ? '🔊' : '🔇'}</button>
|
|
361
366
|
{fsAvailable && (
|
|
362
367
|
<button className="icon-btn" onClick={fsToggle} aria-label={t('fullscreen')}>{isFs ? '🡼' : '⛶'}</button>
|
|
363
368
|
)}
|
package/murdoku.bundle
CHANGED
|
Binary file
|
package/package.json
CHANGED