12 KiB
12 KiB
14 · 向导交互层设计裁定(v1 基线)
依据:research/02-methodology/methodology.md §3(L3 状态层 / L4 引导层)→ research/03-schemes/schemes.md §1/§2(实施蓝图,唯一事实源)。 本文存档 v1 已落地的裁定与新增语音资产台词表,供后续轮次回溯。 实现载体:
web/engine/guide.js(引擎向导模块)+ 各游戏 game.js 接线。
1. 裁定摘要
| # | 裁定 | 内容 |
|---|---|---|
| 1 | 分期 | v1 只做「全局基线」= 引擎向导层 + 逐游戏接线;场景参数包(A 通勤/B 摸鱼/C 睡前/D 下班)与人设旋钮在试玩验证后分期(schemes §3)。 |
| 2 | 等级 | settings.guide:'full'(默认,earcon+语音+震动)/ 'standard'(earcon+震动,无语音)/ 'off'(全静 no-op,不挂任何定时器)。大厅设置面板「向导帮助:详细/只听提示音/关闭」。 |
| 3 | earcon | 8 个签名(6 状态 menu/explore/battle/choice/settle/danger + 2 功能 turn/nudge)全项目统一,全部运行时 WebAudio 合成(零资产、可复现);总长 0.25 |
| 4 | 语音纪律 | 向导插播语音一律 queue:true(等当前对白播完),绝不顶掉正在播的内容;抉择提示(storyline p*)播完即可选的等待点不插任何语音。 |
| 5 | 看门狗 | 统一模板:静默 N 秒 → nudge 轻 earcon(+ full 档语音)→ 二次升级播上下文提示 → 级数用尽自动停止;任何手势/向导动作复位。escape 的三级卡关骨架保留,仅加「连续撞墙 ≥2 次 → full 档阈值提前一级」。 |
| 6 | 引擎配套 | audio.isVoicePlaying() 公开只读 API(收编 5 处私有 _voice 读);audio.setRateBoostEnabled(bool) 长按快进 per-game 开关(rhythm/space 对局期豁免);settings.speed 增加 2.2 档(视障档,250+ WPM)。 |
| 7 | 语义分工铁律 | 语音说「你要做什么」、earcon 说「哪类事/哪个状态」、BGM 说「宏观状态」、震动说「刚才那下对不对」——向导层不越界(L2 铁律:earcon 只做粗标记,语义靠语音)。 |
2. 逐游戏接线裁定(v1 落地范围)
| 游戏 | 接线 |
|---|---|
| storyline | W1/W3 静默看门狗 [8s]=nudge+gd_continue、[20s]=复用 playHelpAndResume;选择节点外左右滑的静默 return 处加 error 震+gd_invalid;抉择态(p* 播完)不插语音不挂看门狗;状态签名 explore/menu 与状态 BGM 同点。 |
| simon | input 看门狗 [10s]=nudge+gd_relisten、[25s]=免扣机会自动重听(每局 2 次);your_turn 泛化为 turn earcon(每轮,第 1 轮保留原语音);状态签名 settle/menu。 |
| escape | REOPEN 提示播完与引导步解锁给 turn cue;连续撞墙 ≥2 次 → full 档卡关三级阈值提前一级;其余(wrong/blunt/stuck/nav)保持既有完备体系。 |
| rhythm | 每曲首次领奏→应答切换推 gd_answer(谱面排程处入 _timed);连续 2 Miss 播 gd_miss(queue 插播,同曲一次);结算链换 _speakGuarded;main 演奏期 setRateBoostEnabled(false);状态签名 menu/battle/settle。 |
| space | 对局第 1 次受击(保护期外)追加 gd_hit_hint;结算链换 _speakGuarded;对局期 setRateBoostEnabled(false);状态签名 battle/menu/settle。 |
| rpg | 格挡窗口内做错手势 → error 震+gd_parry_miss(每局一次);PLAYER_SELECT 挂看门狗 [60s]=nudge+gd_stall;状态签名 explore/battle/menu/settle 与四状态 BGM 同点补齐。 |
3. 新增语音资产台词表(8 句 ×2 性别 = 16 文件)
定稿依据 schemes.md §1.5,台词全文一字不改;speaker/instruct 沿用各游戏旁白常量
(见 tools/gen_voice_dual.py SPEAKERS 与各 _XXX pair):
| 游戏 | id | 全文 | 触发 | female speaker / instruct | male speaker / instruct |
|---|---|---|---|---|---|
| storyline | gd_continue |
轻触屏幕,继续。 | W1/W3 叙事节点播完静默 8s(看门狗第 1 级) | Vivian / _SL_NARR[1] | Uncle_Fu / _SL_NARR[0] |
| storyline | gd_invalid |
这个操作在这里用不上。 | 无效手势(选择节点外左右滑静默 return,同局限次) | Vivian / _SL_NARR[1] | Uncle_Fu / _SL_NARR[0] |
| simon | gd_relisten |
需要的话,双击可以重新听一遍序列。 | input 阶段 10s 无输入(不改变重听扣机会规则) | Serena / _SIMON | Uncle_Fu / _SIMON |
| rhythm | gd_answer |
现在跟着我打。 | 每曲首次领奏→应答切换 | Vivian / _RHY | Uncle_Fu / _RHY |
| rhythm | gd_miss |
慢了半拍,下一小节跟上我就行。 | 连续 2 次 Miss(同曲限 1 次,queue 插播) | Vivian / _RHY | Uncle_Fu / _RHY |
| space | gd_hit_hint |
被撞了。听方位,同向滑动就能拨开。 | 对局第 1 次受击(保护期外,同局 1 次) | Serena / _SPC | Uncle_Fu / _SPC |
| rpg | gd_parry_miss |
前摇声起的时候双击,才能格挡。 | 格挡窗口内做错手势(每局限次) | Serena / _RPG | Uncle_Fu / _RPG |
| rpg | gd_stall |
想好了吗?左右滑动选择,单击出手。 | PLAYER_SELECT 60s 无输入 | Serena / _RPG | Uncle_Fu / _RPG |
资产落位:web/<game>/audio/voice/{female,male}/gd_*.{ogg,m4a}(管线
tools/gen_voice_dual.py --game <g> --only gd_xxx 生成 + --convert 落盘,
双格式配对由 tools/check_all_assets.py 终检保证)。
4. 已知边界与后续候选
onceKey语义为「同局(游戏会话)一次」;schemes §1.5 中 storylinegd_invalid「同局限 2 次」、rpggd_parry_miss「每场战斗 1 次」为更细粒度限次,v1 统一收敛到 onceKey(一次教学提示足矣),如试玩反馈不足再引入 per-run 限次 API。- 教学义务(schemes §1.4「full 档开场教学带教签名 earcon」):v1 未在各游戏教学链中 逐个口播签名音,列为 v2 候选(需逐游戏改教学台词,涉及台词表返工)。
- 向导插播语音目前挂在引擎 voice 队列;若游戏层
stopVoice()会顺带丢弃排队中的 向导句(作废语义,可接受)。
14 · 向导交互层设计裁定(round2 v1.1 增补)
依据:research/04-playtests/round1/synthesis.md(F1~F9 + §3 新语音表,唯一事实源)。 本文只做追加,上文 v1 基线裁定不回改;实现载体同 v1(
web/engine/guide.js
- 各游戏 game.js 接线),全部改动已落地。
5. round2 裁定落地摘要(F1~F9)
| # | 裁定 | 落地 |
|---|---|---|
| F1.1 | storyline 看门狗礼仪 | at [8s,20s]→[25s,50s];say [gd_continue, gd_again];删除升级重播 help+进度+当前节点的 playHelpAndResume 逻辑(_guideHelped 一并移除);两级用尽彻底静默(引擎既有)。 |
| F1.2 | simon 25s 升级去泄题 | 取消免扣机会自动重播序列(_guideAutoRelisten/GUIDE_AUTO_RELISTEN_MAX 删除)→ 改为 guide.turn({haptic:true})(confirm 震 + turn earcon,纯标记无语音)。 |
| F1.3 | rpg PLAYER_SELECT 看门狗 | 60s→30s(gd_stall 不变)。 |
| F1.4 | 空闲才播(idle-only) | guide._say 对 error / watchdog 两类:audio.isVoicePlaying() 为 true 时跳过语音只发事件(事件带 skipped:true)——修「纠错句排到语音链尾迟到误导」;turn 保持 queue 不变。error 的 onceKey 只在语音真的播出时才计数(没听到不算说过)。space 的 gd_hit_hint/gd_last_life 接线点随之外移到受击归因链播完后的空闲点,否则会被自家归因句判为「在播」整段跳过。 |
| F2.1 | rhythm 教学首次归因 | 教学步首次失败即在纠正链(retry_* + retry_listen)播完后的空闲点发分档句:方向错 gd_miss_wrong / 抢拍 gd_miss_early / 慢拍 gd_miss_late;判定沿用 _tutAttempts(手势错 > dt<0 > dt>0),无窗内尝试(没出手)归入 gd_miss_late;第二次失败走 retry_skip 不再叠加归因。正片连 2 Miss 仍用 gd_miss。 |
| F2.2 | space 受击经济透明 | 第 2 次受击在 hit_<dir>+hit_last 链播完后发 gd_last_life(见 F1.4 接线点说明)。 |
| F2.3 | escape 撞墙报方位 | 撞墙在既有 voice/wall 播完后接既有 guide_blunt_<dir> 方向句(资产 v1 已有,纯逻辑接线;被下一次移动打断则自然作废)。全档位生效(游戏反馈层,非 full 档专属)。 |
| F3.1 | rhythm 交接提前 | gd_answer 不再走 guide 的 queue——由 guide.turn({}) 发 turn earcon、语音由曲谱定时队列(_timed,首个应答窗口前一小节头)在 full 档直接落下,保证窗口前听到。 |
| F3.2 | 断点续播 count-in | 暂停菜单恢复时网格/BGM 整体后移一小节,前 4 拍用底鼓(inst_kick 0.7)+beat 轻震做 count-in(走既有 _sched 网格排程);off 档保持原即时续播(零改动路径)。 |
| F4 | rpg 教学看表现 | T2 格挡成功通过时插 tut_b2b「挡得漂亮。」再进 T3;失败路径(tut_b4)不变。 |
| F5 | simon 经济透明 | 教学收尾链改为 t7_ready→t7_retry→gd_economy→开局(guard 12s→20s)。作为游戏规则句随教学链播(全档位),与 skip_hint 同类。 |
| F6 | space 警报叠爆 | 警报音效按 soft/loud 两档各自 600ms 窗口去重(双陨石同时逼近只起一波渐强警报,单颗两段渐强不受影响);danger 震全局限 ≥400ms 间隔。 |
| F7 | rpg 菜单回绕 | 探索选项列表与战斗指令循环:右滑回首项→gd_wrap_first、左滑到末项→gd_wrap_last;full 档 queue 跟在本项报名之后,同一次菜单打开内每句最多 1 次(_wrapShown 在进场景/进入玩家回合时重置);被下一次滑动打断则自然作废。 |
| F8 | storyline 开场瘦身 | 开场链最前插 gd_brief(full 档,brief→intro);intro 长句资产保留不动。 |
| F9 | 语速演示 | round2 会话剧本在 storyline 段演示 settings.speed=2.2 切换(转写可见),产品代码零改动(v1 已支持)。 |
6. round2 新增语音资产台词表(10 句 ×2 性别 = 20 文件)
全文与 synthesis §3 逐字一致;speaker/instruct 沿用各游戏旁白 pair 常量:
| 游戏 | id | 全文 | 触发 |
|---|---|---|---|
| storyline | gd_brief |
单击继续剧情。请选择的时候,左右滑动。 | 开场链最前(F8,full 档) |
| storyline | gd_again |
还在吗?单击继续。 | 看门狗 50s 升级(F1.1,替代重播 help) |
| rhythm | gd_miss_early |
抢拍了。等声音落下再滑。 | 教学 Miss 且抢拍(F2.1) |
| rhythm | gd_miss_late |
慢了半拍。跟着节拍走。 | 教学 Miss 且慢拍/没出手(F2.1) |
| rhythm | gd_miss_wrong |
方向不对。跟着音色滑。 | 教学 Miss 且手势方向错(F2.1) |
| simon | gd_economy |
记不住就双击重新听,免费机会有两次,用完要扣一次机会。 | 开局教学末尾(F5,全档位) |
| space | gd_last_life |
这是最后一次机会,撑住。 | 第 2 次受击(F2.2,归因链后空闲点) |
| rpg | tut_b2b |
挡得漂亮。 | 教学 T2 格挡成功(F4,全档位) |
| rpg | gd_wrap_first |
回到第一个。 | 菜单/指令循环切回首项(F7,full 档) |
| rpg | gd_wrap_last |
最后一个了。 | 循环切到末项(F7,full 档) |
7. round2 验证记录
- 6 playtest(guide=off):断言零改动全绿(storyline 54 / escape 103 / simon 108 / rhythm 81 / space 113 / rpg 139,与 v1 基线一致)。
web/harness/guide.test.mjs52 断言全绿:storyline 25s/50s 新节奏 + 无重播断言、 simon 25s 无序列重播 + confirm 震/turn 事件、F1.4 idle-skip 直连断言(watchdog/ error 在播跳过 + 空闲播放 + turn 保持 queue)、off 档全静零定时器。tools/check_all_assets.py全绿(双格式配对、无 0 字节、全可解码、双性别集合一致);tools/extract_voice_text.py已刷新web/harness/voice_text.json(428 句)。- 转写渲染适配:实际播出的
voice/gd_*由 play 捕获照常渲染;被 idle-skip 的 向导句单独标注「本句按 idle-only 跳过未播」。