Files
Toolbox/public/tools/thought_lab/labs/physics_balls/pb_audio.js
T
yangxiangyuan 91148fe064 feat: 新增物理弹球实验室及配套功能
1. 新增物理弹球游戏全套代码,包含物理引擎、规则、渲染、游戏逻辑、存档、音效、UI
2. 新增物理弹球相关调试与单元测试脚本
3. 优化私有剪贴上传功能:增加200MB上传限制与错误提示
4. 修复复古弹球桌的光滑面防粘附与休眠逻辑
2026-08-08 22:31:33 +08:00

60 lines
2.2 KiB
JavaScript

/* ============================================================
* pb_audio.js · 物理弹球 Web 复刻版 · WebAudio 合成音效
* 无外部资源:发射/击中/碎裂/道具/结束 均为振荡器合成。
* 设置页可开关(PBStorage.soundOn)。
* ============================================================ */
var PBAudio = (function () {
'use strict';
var ctx = null;
var lastHit = 0, lastWall = 0; // 分开节流,防砖块命中音被墙壁音吃掉
function ac() {
if (!ctx) {
try { ctx = new (window.AudioContext || window.webkitAudioContext)(); } catch (e) { ctx = null; }
}
if (ctx && ctx.state === 'suspended') { try { ctx.resume(); } catch (e) {} }
return ctx;
}
function enabled() {
try { return PBStorage.soundOn(); } catch (e) { return true; }
}
function tone(freq, dur, type, gain, slideTo) {
var c = ac();
if (!c || !enabled()) return;
try {
var o = c.createOscillator();
var g = c.createGain();
o.type = type || 'sine';
o.frequency.setValueAtTime(freq, c.currentTime);
if (slideTo) o.frequency.exponentialRampToValueAtTime(slideTo, c.currentTime + dur);
g.gain.setValueAtTime(gain || 0.08, c.currentTime);
g.gain.exponentialRampToValueAtTime(0.0001, c.currentTime + dur);
o.connect(g); g.connect(c.destination);
o.start(); o.stop(c.currentTime + dur + 0.02);
} catch (e) {}
}
return {
unlock: function () { ac(); },
fire: function () { tone(520, 0.12, 'triangle', 0.06, 260); },
hit: function (speed) {
var now = Date.now();
if (now - lastHit < 45) return; // 限流防炸音
lastHit = now;
tone(300 + Math.min(500, speed * 0.15), 0.06, 'square', 0.035);
},
wall: function () {
var now = Date.now();
if (now - lastWall < 45) return;
lastWall = now;
tone(180, 0.05, 'sine', 0.03);
},
breakBlock: function () { tone(760, 0.16, 'sawtooth', 0.06, 180); },
item: function () { tone(660, 0.1, 'sine', 0.07, 990); tone(990, 0.16, 'sine', 0.06, 1320); },
over: function () { tone(392, 0.25, 'triangle', 0.08, 196); },
claim: function () { tone(523, 0.09, 'sine', 0.07); tone(659, 0.09, 'sine', 0.07); tone(784, 0.16, 'sine', 0.07); }
};
})();