按 docs/design/26-audio-interaction-playbook.md 重构三款游戏(对白重写 + 双性别语音重生成 580 文件)。 引擎层(web/engine/,其余 12 款游戏零改动): - floor.js 发言权管理器:SPEAKING/YOUR_TURN/BUSY/ACTION 四态、交接提示音、 等待声(220/330Hz 嘟-嘟,20s 后放缓)、跨链音乐压低(audio.js holdDuck) - receipts.js 输入回执三件套(ok/invalid/busy,100ms 内,原则 4) - confusion.js 迷茫检测(乱点/无效/静默信号 → 三级接管,§4.5) - hints.js 等待点 + 三档提示(full→short→提示音,30s 台账跨点去重,原则 9) - novice.js 手势解锁阶梯(up/down/doubletap 跨局持久,§4.3) - pipeline.js 输入管道(回执收口、防连点 400ms、双击折算、explainOnce) 游戏层: - storyline R3:开场 71.7s 规则念白 → 3 秒内动手;双击=重播(反模式5)废除; 抉择点三档提示+主动重听;断点存档复述(§4.12) - escape R3:单击=检查+使用合并(双击用法废除);长按=我在哪(四向玩法裁定); 撞墙归因每方向一次(原则 7);迷茫 L2 缩小/L3 演示;坐标存档续玩 - simon R3:新手三音色,按实力渐进解锁(+up/down/dt);失败表替代机会账 (归因 2s 内→免费重听→放慢→结算,原则 15);播放期手势=busy 回执 测试:三款 playtest 重写(含 §6.2 乱点机器人:无声操作/被动重复/打断失败全 0, 首操作 ~2s);guide.test 改为 Guide 层单测+rhythm/space 段。全部通过 (38+33+22+72+19+35 断言)。设计单见 docs/design/26-apply-*.md。
46 lines
1.5 KiB
HTML
46 lines
1.5 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
|
||
<title>音序回响 · SoundGame Web</title>
|
||
<link rel="stylesheet" href="../engine/style.css">
|
||
</head>
|
||
<body>
|
||
<div id="game-root">
|
||
<img class="cover" src="cover.png" alt="">
|
||
</div>
|
||
|
||
<script type="module">
|
||
import { WebAudioEngine } from '../engine/audio.js';
|
||
import { attachGestures } from '../engine/gesture.js';
|
||
import { makeInputPipeline } from '../engine/pipeline.js';
|
||
import { SimonGame } from './game.js';
|
||
|
||
async function main() {
|
||
const root = document.getElementById('game-root');
|
||
const audio = new WebAudioEngine('audio/');
|
||
const game = new SimonGame(audio, root);
|
||
|
||
await audio.showStartOverlay({ cover: 'cover.png' });
|
||
// 走到这里 AudioContext 已解锁,可以出声了
|
||
game.start();
|
||
// 26 号文档 §4.2/§4.3:手势回调走输入管道;doubleTapWindow=0 关掉双击、
|
||
// 单击零延迟(键盘回车发的 doubletap 在管道里折算成 tap)
|
||
const onGesture = makeInputPipeline({
|
||
floor: game.floor,
|
||
confusion: game.confusion,
|
||
receipts: game.receipts,
|
||
invalidHints: game.invalidHints,
|
||
game,
|
||
ladder: game.ladder,
|
||
opts: game.PIPELINE_OPTS || {},
|
||
});
|
||
attachGestures(root, onGesture, { doubleTapWindow: 0 });
|
||
}
|
||
|
||
main();
|
||
</script>
|
||
</body>
|
||
</html>
|