feat: 新增物理弹球实验室及配套功能
1. 新增物理弹球游戏全套代码,包含物理引擎、规则、渲染、游戏逻辑、存档、音效、UI 2. 新增物理弹球相关调试与单元测试脚本 3. 优化私有剪贴上传功能:增加200MB上传限制与错误提示 4. 修复复古弹球桌的光滑面防粘附与休眠逻辑
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
/* ============================================================
|
||||
* 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); }
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user