- S2:新增input_open双音柔铃标记「能答了」边界(playback/input边界此前吞手势无标记) - S1/S3/S4:input阶段长按=状态查询(13句status_*分档整句:长度4档×进度4档×账目5档,两本账口径一致,不耗账不闭窗) - S5:announce/roundend非单击手势补error震(00 §5.4三秒反馈律) - S6 P0:gameover下滑进菜单→结算链死锁8.4s修复(结算看守+挂起补播) - S7:your_turn每局一次(原每轮重念) - 取证:live两会话+4人设评审,S清单见research/simon-polish/round1/findings.md - 验证:playtest 156/156 + guide 122 + 终检绿 + 14游戏回归零回退 + live复跑核对局14/14压力局8/8;状态感知2/5→4/5(四席同升),愿意玩改口为是 - 02号文档追加§9修订记录;新增input_open+13句status_*走完整TTS管线(flock串行QC无离群)
12 KiB
02 · 《音序回响》重设计(simon redesign)
给开发者的实现要点摘要
- 删除 BGM:
bgm/theme不再播放,游戏只有交互音色 + 语音两条线(响应反馈⑥)。- 旁白全部整句化:删除
di/lun/num_*/score_pre/best_pre拼接体系,轮次与成绩改预生成整句(轮数 1-20 逐句 + 无数字兜底;成绩分段整句)。- 交互节奏:播放序列时每个音前给
BEAT轻震提供节拍感;复现阶段每个手势给CONFIRM震动确认;对/错用 SUCCESS/ERROR 震动,sfx/correct、sfx/wrong提示音删除。- 教学改交互式:每教一个音色就让玩家亲手做一次该手势,做对才教下一个。
- 人性化与复活:每局初始 1 次"重听机会"(输入阶段双击=重听当前序列,消耗机会;答错时若有机会则消耗一次机会重听而非直接结算),每过 4 轮 +1 次(上限 2);速度爬升放缓;前 5 轮避免同手势三连。
1. 现版诊断
读 web/simon/game.js:
- BGM 是干扰项(
bgm/theme音量 0.4 常驻,game.js:77)。记忆类游戏的工作记忆负载全在听觉通道,BGM 与六个手势音色同通道竞争,是纯负面。反馈⑥正确,整层去掉。 - 数字拼接是音色漂移重灾区:报轮次
di + num_5 + lun、报成绩score_pre + num_* + lun(game.js:47-57, 142, 219-222)。这正是反馈⑥"音色漂移发音不准"的来源。 - 教学是 8 句连续旁白(
_runTutorial, game.js:92-117),玩家只能听不能动,听完直接开考。 - 错一音即死(
_onInput→_gameOver),无缓冲;轮次越高挫败越强。 - 反馈音与内容音同质:
sfx/correct/sfx/wrong与手势音色同为合成短音,盲听时"我按对了还是错了"要靠音色分辨,混淆。
2. 音频层重构
- BGM 层:不播放、不加载。开场静默 0.5s 后直接进教学语音。间隙的"空白感"由环境底噪填充?——不填。纯静更利于记忆,这是设计选择不是缺失。
- 手势音色(
tone_*6 个):保留现有映射(上=上行琶音 / 下=下行低音 / 左=左声道弹拨 / 右=右声道弹拨 / 单击=底鼓 / 双击=双连响),这是游戏内容,不动。 - 反馈提示音(
sfx/correct、sfx/wrong、sfx/newrecord):删除,改震动(见 §4)。sfx/gameover保留为内容性结束音(低沉闷响,标识一局终结,不与任何手势音色相似)。
3. 旁白整句化清单
3.1 删除的拼接件
voice/di、voice/lun、voice/num_shi、voice/num_0..9、voice/score_pre、voice/best_pre 全部退役(资产文件可留,代码不再引用)。
3.2 需要重录的句子类型(整句,female/male 双目录)
| 类型 | 句数 | 说明 |
|---|---|---|
| 轮次播报 | 21 | "第一轮,听好了。"…"第二十轮,听好了。"逐轮整句;第 21 句为无数字兜底:"新的一轮,听好了。"(round>20 时用,轮次仍可继续) |
| 成绩播报 | 6 段 | 按完成轮数分段整句:"一轮都没坚持下来,别灰心。"/"你坚持了三轮以内。"/"你坚持了五轮左右。"/"你坚持了将近十轮。"/"你坚持了十轮以上,很厉害。"/"你坚持了十五轮以上,大师级。"(代码按 score 映射分段) |
| 新纪录 | 1 | "新纪录!"(已是整句,保留文本重录) |
| 教学句 | 8 | 见 §5,每句 ≤20 字 |
| 流程句 | 6 | "轮到你了。"/"重听机会用完了,小心。"/"用一次机会,再听一遍。"/"单击屏幕,再来一局。"/"上滑重听规则,下滑打开菜单。"/规则重听句 |
| 反馈短句 | 3 | "答对了!"/"错了。"/"机会加一。"(均已有文本,整句重录) |
生成规范按 00 文档 §3:同一 SPEAKER 常量(female=Serena / male=Uncle_Fu)+ 同一 INSTRUCT 常量(建议"平静清晰的女声/男声,语速平稳"——不写进 instruct 的语速词,instruct 只控情绪:"平静、清晰、像游戏主持人")。
4. 交互节奏与震动设计
4.1 播放序列阶段(playback)
- 每个手势音播放的同时给
BEAT(8ms 轻震):节拍锚点帮助玩家分段记忆(把 N 个音切成节拍组),这是 simon 类游戏经典的"chunking"辅助。 - 播放间隔维持"逐个播放",节奏均匀(见 §6 速度曲线),最后一个音播完 400ms 后给一次
CONFIRM震动,表示"轮到你了"(第 1 轮同时播语音,之后轮次只用震动,省时间)。 - 播放阶段手势一律忽略(保留现行为),但给
ERROR震动一次告知"现在不用操作"?——不给,播放期误触静默忽略,避免打断聆听(00 文档 §2.4:纯聆听阶段不震动,BEAT 除外因其本身是节拍信息)。
4.2 复现阶段(input)
| 事件 | 震动 | 音频 |
|---|---|---|
| 玩家做出手势 | CONFIRM | 立即回声放对应手势音色(保留现行为) |
| 手势正确(序列推进) | (并入上面的 CONFIRM,不额外震) | — |
| 整轮复现成功 | SUCCESS | "答对了!"(每轮都播太密——改为每 4 轮播一次,其余轮次仅震动) |
| 答错且有机会 | ERROR + WARNING(间隔 300ms 先后) | "错了。用一次机会,再听一遍。" → 自动重播序列 |
| 答错且无机会 | ERROR + HIT | sfx/gameover + 成绩播报 |
| 双击(消耗机会主动重听) | PICKUP | "再听一遍。"+ 重播序列(inputIdx 重置为 0) |
| 机会 +1(每过 4 轮) | PICKUP | "机会加一。" |
5. 交互式教学(tutorial)
现版 8 句连播改为"教一个、练一个":
| 步 | 语音(整句) | 机制 |
|---|---|---|
| T0 | "欢迎来到音序回响。我会演奏一串声音,请你记住顺序,原样复现。先认识六种声音。" | 播完进 T1 |
| T1-T6 | 每个手势一句:"向上滑,是这个声音。"→ 播 tone → "你试试。" | 等待玩家做出该手势;做对:tone 回响 + CONFIRM 震动 + "对了。"进下一个;做错:ERROR 震动 + "不是这个,向上滑试试。"重等;同一手势错 3 次给更直白描述("手指贴着屏幕,向上推一下") |
| T7 | "六种声音都记住了。序列会越来越长,答错可以消耗机会重听。双击随时重听当前序列。" | 进 T8 |
| T8 | "第一轮,听好了。" | 进正式对局 |
教学时长约 60-80s,全程玩家动手 6 次以上。教学期间下滑=跳过教学(播确认句后直达第一轮)。
6. 难度曲线与复活机制
6.1 速度曲线(放缓)
现版 _interval(): 720ms 起、每轮 -36ms、下限 340ms(game.js:152)——第 11 轮即触底。新版:
interval(round) = max(420, 700 - (round - 1) * 25) // 第 12 轮才到 420ms 下限
6.2 序列生成约束
- 长度 = round + 1(保留,从 2 开始)。
- 前 5 轮:禁止同一手势连续出现 3 次;第 1 轮两个音不同手势。
- 全部轮次:禁止连续 4 个同手势(防恶意随机)。
- 复活重听的序列不变(重听就是重听同一序列,不重新随机)。
6.3 机会(retry)规则
- 每局初始
chances = 1;每完成 4 轮chances = min(2, chances + 1)并播报。 - 消耗途径二选一:a) 输入阶段双击主动重听当前序列(进度清零重输);b) 答错时自动消耗一次机会,重播序列后再试。
- 双击语义冲突的裁定(R3 修订,round2-review 裁决①):输入阶段双击按上下文判定——当前期望输入恰为 doubletap 时双击=答题(序列必须永远可答,答题优先),否则双击=主动重听(耗机会)。机会为 0 时双击非期望手势:不判答错、不消耗,仅播
chances_out提示。重听播报期间切到非输入阶段,避免手势被吞。 - 无机会时答错 → gameover:成绩分段整句播报 + 新纪录判定 + "单击屏幕,再来一局"。
best(历史最高)从会话内存改为写进度存储(localStorage + 服务器同步,进度 data 带summary,格式"最佳成绩:第 N 轮")。
7. 状态机与手势汇总
阶段:tutorial → announce → playback → input → (replay) → roundend → … → gameover
| 阶段 | 上滑 | 下滑 | 双击 | 单击 | 四向滑/点按 |
|---|---|---|---|---|---|
| tutorial | — | 跳过教学 | — | — | 教学输入 |
| playback | — | — | — | — | 忽略 |
| input | — | — | 重听(耗机会) | 答题输入 | 答题输入 |
| gameover | 重听规则 | 菜单(重开/回大厅) | — | 重开 | — |
非 input 阶段上滑=重听规则(豁免见 00 文档 §5.2:六手势全是输入,帮助让位到非输入阶段)。
8. 资产清单变动
- 删:bgm/theme 引用(文件可保留不播)、sfx/correct、sfx/wrong、拼接数字件。
- 新录:§3.2 全部(约 45 句 × 2 音色 = 90 条 × 2 格式)。
- 保留:6 个 tone、sfx/gameover。
- 更新
web/simon/README.md玩法描述与gen/gen_voice.py的LINES表(文本表驱动,female/male 两跑)。
9. 修订记录(追加;旧文不动)
round5(2026-09-14,research/simon-polish/round1 取证 → round2 修复;S1-S7)
用户真机反馈"玩法保留,但不清楚自己当前的状态"。round1 取证(剧本转写 + live 两会话: 认真新手局 13 轮 + 急性子乱按局)落成 S1-S8(research/simon-polish/round1/findings.md), 本轮修复 S1-S7,玩法零改动,只加状态透明层:
- S2 · input 开放标记音
sfx/input_open:_toInput播放(游戏层资产,三档 guide / iOS 无震动全可闻)。confirm 震只标记"播放完毕",占用预告/your_turn 语音 链播完才真开放——取证中该窗口内作答被静默吞(live-A 行 108-115)。无语音链的 轮次不再叠向导 turn earcon,input_open 独立作边界标记(二选一不叠响)。 - S1/S3/S4 · input 阶段长按=状态查询(
_statusQuery,13 句status_*分档 整句,见 02b 追加节):长度 4 档 × 进度 4 档 × 重听账目 5 档(下一次重听消耗哪个 桶,与 §6.3 两账口径一致)。长按是六手势全被玩法占用下唯一的空闲键位(键盘= 按住空格,00 §5.5 通道自动获得);玩家主动查询,三档 guide 全可用,不耗账、 不判错、不清进度、不闭作答窗口。查询只绑定 input 阶段——playback 维持纯聆听 豁免(§4.1),查询语音会污染记忆任务。 - S5 · announce/roundend 误触给 error 震:非单击手势在播报/表扬链期间不再 静默吞(00 §5.4 三秒反馈律);playback 维持 §4.1 静默豁免不动。
- S6 · 结算语音链阶段看守:链只在结算屏交付——gameover 瞬间下滑进菜单则挂起,
回结算屏补播(
_deliverSettle/_backToSettle)。承诺「单击屏幕,再来一局」 永远与所处相位一致(取证:链在菜单内播完 → 承诺在菜单内是假的 → 关菜单后结算 屏死寂 8.4s,live-B 行 140-174)。重开/回大厅作废挂起链。 - S7 ·
your_turn每局一次:第 1 轮复活/重听的重播不再重念(取证一局三遍, live-B 行 67/96-98)。
验证:playtest 156 断言全绿(新增 S2-S7 断言 + 场景三专项);guide.test 122 断言 全绿;check_all_assets 15 游戏全绿;其余 14 款游戏 playtest 回归全绿。修后 live 两会话复跑(research/simon-polish/round2/):核对局 V 14/14、压力局 P 8/8 断言通过, ASR 非 OK 行全部归因玩家自裁(跳旁白截断/短句同音近失/补播抢占),无游戏自残; 四人设复审闭环(round2/p*.md,状态感知 2/5→4/5 across 四席,P0 清零)。