Files
2026-10-01 23:26:47 +08:00

257 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 15 · 《不眠频率》(radio) — 深夜电台热线叙事 RPG
> **给开发的实现要点摘要**
> 1. 交互权威:[26-audio-interaction-playbook.md](26-audio-interaction-playbook.md)。本文件按附录 C 填写;与旧手势表冲突时以本文为准。范式对齐 [26-apply-storyline.md](26-apply-storyline.md)。
> 2. 叙事骨架不变:节点链 onComplete 串行 + seqToken 打断作废 + pendingChoice 缓存;6 宏状态 INTRO / RING / ONAIR / BRIDGE / ENDING + MENU。
> 3. 新手三手势:单击继续/接听、左右滑抉择、上滑「我在哪」。**不识别双击**。无四向滑动玩法,帮助不上长按。菜单:左右滑切换、单击确认。
> 4. 台词 [15-radio-voice-ids.md](15-radio-voice-ids.md)(132 句:双性别 103 + 平铺 NPC 29)。NPC 电话滤波在资产侧 ffmpeg 带通,引擎零改动。
> 5. 章程:单局 15–25 分钟、9 抉择点、4 结局、分支局部化。开场砍长规矩:3 秒内动手,10 秒内接听成功。
---
## 附录 C · 设计单
### 1. 一句话核心动作
**听一段热线,单击继续或接听;听到选项时左右滑做决定。**
### 2. 玩家能感知的状态(3 个)
| 状态 | 听感 | Floor |
|---|---|---|
| 听讲 | 主播/来电者语音,BGM 整链压低 | SPEAKING |
| 轮到你 | 风铃 `turn` → 400ms 后等待声(RING 用铃声循环代替合成等待声) | YOUR_TURN |
| (菜单/结算为元状态,`menu`/`settle` earcon + 结算句标识,不占新手三态) | | |
RING 的铃声循环即等待声身份;首次出现配一句:「灯亮了,点一下接听。」
### 3. 新手手势与解锁
| 手势 | 含义 | 解锁 |
|---|---|---|
| 单击 | 继续 / 接听 / 跳过当前这句 | 阶段 0 |
| 左滑 / 右滑 | 抉择(左=走心,右=克制) | 阶段 0 |
| 上滑 | 我在哪(通号 → 口碑 → 一个动作,≤20 字) | 阶段 1(第一次抉择后) |
| 下滑 | 菜单 | 阶段 2(第一次到达结局) |
| 双击 | 新手期不存在,按单击处理。阶段 3 起=重听**当前等待点完整句**(加「再说一遍:」)。禁止绑整节点重播 | 阶段 3(累计 3 局) |
| 长按 | 新手期 `invalid`。未占用帮助:旁白加速(12 号) | — |
### 4. 状态 × 手势矩阵(新手期)
| 状态 \ 手势 | 单击 | 左/右滑 | 上滑 | 下滑(未解锁) | 双击 | 连点 |
|---|---|---|---|---|---|---|
| 游戏在说 | 跳过这句 + ok(p* / 链末关键句除外 → busy) | 打断后:抉择点缓存 pendingChoice、不盲选;非抉择点 invalid+解释一次 | 打断,答「我在哪」 | invalid + 首次解释 | 按单击 | 400ms 内 busy |
| 等你继续 | 继续 + ok | invalid(「现在不用选。单击继续。」) | 我在哪 | invalid | 按单击 | busy |
| RING 等接听 | 接听 + line_connect(silent-ok) | invalid + 首次解释 | 「第 N 通。点一下接听。」 | invalid | 按单击 | 400ms 内 busy |
| 等你选择 | 再听选项(「再说一遍:」+ 完整句,hold) | 抉择 + ok | 「正在抉择。左右滑。」 | invalid | 按单击 | 计入迷茫 |
| 结算 | 新夜班 + ok | invalid | 重播结局+口碑一句 | 菜单(阶段2) | 按单击 | 只处理第一下 |
| 菜单 | **确认当前项** + ok | 右=下一项 / 左=上一项,每项报名 | 重听菜单说明 | 关闭 | 按单击 | busy |
验收:无空格;无「没有声音」;连点无重播/重开。
**跳过纪律(G5,无双击重播)**:首播必完整——p* 不可跳、链末交接句不可跳、ASK 恢复首句锁。复播(关菜单复述)可掐。p* 播放中左右滑只缓存,句尾生效。
### 5. 等待点配置
| id | 期待 | full | short | 静默 | L2 只留 | L3 演示 | 失败归因 |
|---|---|---|---|---|---|---|---|
| intro | tap | 「点一下屏幕。」 | 「点一下。」 | 6s / 15s | tap | 替点一下 | — |
| ring | tap | 「热线在闪。点一下,接听。」 | 「点一下。」 | 8s / 18s | tap | 替接听 | — |
| continue | tap | 「单击,继续。」 | 「单击。」 | 18s / 40s | tap | 替继续 | — |
| choice | left/right | 当前 pN | 「左右滑,选。」 | 25s / 50s | 左右滑 | 「左右滑,都可以。现在你来。」 | — |
| settle | tap | 「单击,重新开始。」 | 「单击。」 | 20s / 45s | tap | 提示音 | — |
| reopen | tap/right | sys_continue_ask | 「单击。」 | 12s / 30s | — | 提示音 | — |
| menu | tap/left/right | menu_help | 「左右滑,点一下定。」 | 20s / 45s | — | 提示音 | — |
三档 + 30s 台账去重走引擎 `hints.js`。RING 两级不同句,用尽只留铃声,永不惩罚。
### 6. 首 3 分钟逐秒脚本
| 时间 | 游戏说 / 播 | 期待 | 没做 | 做错 |
|---|---|---|---|---|
| 0~3s | onair_sting + amb_studio →「点一下屏幕。」(critical) | 单击 | 6s:「点一下。」 | 滑动:invalid +「先点一下。」 |
| 3~8s | ok →「热线灯亮了。」→ 铃声 + turn | 单击接听 | 「点一下,接听。」 | 滑动:invalid |
| 8~10s | line_connect + 老周开口(z1_a) | 听 | | |
| 10~15s | 「听到这个声音,就是轮到你了。」→ turn + 等待声 | 单击继续 | 三档 | inv_nosel |
| 15~45s | z1 链 → p1「左滑,哼歌。右滑,问路。」 | 左/右滑 | 复述 p1 | 滑早了:跳去选项句,不盲选 |
| ≈50s | 老周声音稳住 +「对。」解锁上滑:「想知道自己在哪,就向上滑。」 | 上滑 | 「向上滑。」 | 单击=再听选项 |
| 50~180s | p2 与 BRIDGE 口碑;第二通铃 | 单击/滑动 | 迷茫 L1→L3 | 归因真话 |
节奏:3s 内动手 ✓;10s 内接听成功 ✓;每 30s 有通号/对方情绪变化 ✓;无开场念规则 ✓。
### 7. 失败表
| 失败类型 | 判定 | 归因句 | 回到哪里 | 新手期代价 |
|---|---|---|---|---|
| 非抉择点滑动 | 手势与状态不符 | 「现在不用选。单击继续。」 | 原地 | 无 |
| RING 滑错 | RING 左右滑 | 「点一下,接听。」 | 原地 | 无 |
| 静默 | 阈值到点 | 三档提示 | 原地 | 无 |
| 迷茫 | 信号 ≥2 | L1 短句 / L2 只留期待手势 / L3 演示 | 原地 | 无 |
| 负向结果(p1右+p2右) | 计分表 −1 | z1_bade 指向实际选择 | 下一通 | 不扣资源 |
叙事无资源死亡。旧「双击=整节点重播」废除。
### 8. 台词类别
- `critical`:sys_first_tap(开场 ≤3s);RING 首次接听指令
- `content`:b_*、各通对白、p1–p9、e1–e4、ep_*、sys_turn_teach、sys_unlock_*、menu_item*
- `hint`:sys_hint_*_full/short、gd_ring1/2、status/prog/rep_*、sys_continue_ask
- `feedback`:inv_nosel、inv_generic、z1_bade、k1_lulle、k1_liee
- 主动重听前缀:`sys_say_again`
- 完整清单见 `tools/gen_voice_dual.py` RADIO 表(132 句 × 双性别主播/导播 + 29 NPC 平铺 = 235 条,×2 格式 470 文件)
### 9. 断点复述
- 保存:每通 RING、每个抉择后、ENDING、菜单「保存并回大厅」写 `soundgame.radio.save`(phase + node + rep/bond/heardArgument)。
- 回来 5s 内:sys_continue_ask「检测到上次的进度。单击,继续上次。右滑,从头开始。」单击后重播当前节点(局面复述)。
- 上滑复述模板:位置(第 N 通·来电者)。目标(口碑档)。一个动作。
### 10. 测试记录
- 无头:`web/radio/test/playtest.mjs`。乱点机器人须 `guide=full`:无声操作 0、被动原句重复 0、打断失败 0、第一次操作 ≤3s、第一次成功 ≤10s。
- 真人冷启动:待测(26 §6.3)。
---
## 1. 概述
- **一句话**:你是午夜档电台热线主播「今夜不眠」,一晚接进五个来电——你说什么、接不接、转不转接,改变五个陌生人的夜,也改变你自己。
- **声音即世界**:来电者永远不露面,只有滤波后的电话声;直播间垫乐与环境音是空间。
- **单局**:完整夜班 15–22 分钟;五通共享主干,分歧在通内局部化;实走 8–9 个抉择,4 结局。
- **核心循环**:铃响接听 → 听 → 左右滑(走心/克制)→ 结果与口碑 → 幕间喘息 → 下一通。跨通积累 `rep` 与各通 `bond`,收播前 p9 决定心结。
## 2. 状态机
| 状态 | 内容 | BGM | earcon |
|---|---|---|---|
| INTRO | 极短开场后交 RING | `bgm/onair` | explore |
| RING | 铃声循环,等单击接听 | 不切 | turn(铃声承担等待声) |
| ONAIR | 通话链 + 抉择 + 结果 | `bgm/onair` | explore;p*=choice |
| BRIDGE | 口碑跨档(如有)+ 喘息,auto ≤12s | `bgm/bridge` | settle |
| ENDING | 结局 + 五句回响 | `bgm/ending` | settle |
| MENU | 模态覆盖,暂停链 | `bgm/menu` | menu |
```
INTRO ──链完──> RING(c1) ──单击接听──> ONAIR ──链完──> BRIDGE ──> RING(c2) … RING(c5)
ONAIR(c5) ──> BRIDGE ──> ◆p9 ──> ENDING(e1..e4 + ep)
任意叙事态:阶段2 后下滑 → MENU(左右滑切项,单击确认,上滑重听说明,再下滑关闭)
```
- 仅 `node.auto` 或过场自动衔接;其余 ONAIR 链末等单击。
- ASK:单击继续 / 右滑新夜班。
- 关菜单后重播当前节点(局面复述)。
## 3. 抉择树
### 3.1 骨架
```
INTRO ──> 铃①
【C1 老周】教学通 · p1 p2 ──> BRIDGE ──> 铃②
【C2 小鹿】p3 ──> BRIDGE ──> 铃③
【C3 糖糖】p4 p5 · 埋 heardArgument ──> BRIDGE ──> 铃④
【C4 陈姐】p6 p7 · 消费 heardArgument ──> BRIDGE ──> 铃⑤
【C5 老韩】p8 + 危机拍 ──> ◆p9 ──> ENDING
```
跨通只传 `rep`、`bond`(5×0/1)、`heardArgument`。无组合节点。最坏/最好路径节点数相同。树约 60 节点、132 句。
### 3.2 分通(◆=抉择,〔〕=条件差分)
**C1 老周**:铃 → z1_ring_in → z1_a/b → ◆p1 左哼歌 / 右问路 → ◆p2 左陪等 / 右转接(仅 p1=右且 p2=右走 z1_bad 归因)→ z1_ok1(全局一次)→ BRIDGE。
**C2 小鹿**:◆p3 左劝上车 / 右还自由 → BRIDGE。
**C3 糖糖**:k1_b 垫 `arg_muffled` → ◆p4 左哄睡(本通结束)/ 右问她 → ◆p5 左真话(heardArgument=true)/ 右谎言 → BRIDGE。
**C4 陈姐**:◆p6 左带话〔heardArgument ? w1_say : w1_say2〕→ ◆p7 左直播 / 右私聊;p6 右劝回家本通结束 → BRIDGE。
**C5 老韩**:◆p8 左陪聊闺女(danger + brake_screech 前置 2s)/ 右服务区;bond_zhou 时插 h1_echo → ◆p9 左直面 / 右回避 → ENDING。
**结局**
| 结局 | 条件 | 主题 |
|---|---|---|
| e1 天亮之前 | rep≥5 且 p9 左 | 话筒接住了这座城 |
| e2 热线常亮 | rep≥5 且 p9 右 | 满座夜班,留言机未看 |
| e3 一个人的频道 | rep<5 且 p9 左 | 晚安说出去了 |
| e4 静音 | rep<5 且 p9 右 | 谁也接不住谁 |
epilogue 对五人各播 bond? 救到 : 错过。
注:p4 表列「问她/哄睡」与树形(左=哄睡 / 右=问她)以树形与 p4 提示句为准;p4 右 → heardArgument=true。
## 4. 数值
| 变量 | 初值 | 说明 |
|---|---|---|
| `rep` | 0 | 听众口碑 |
| `knot` | false | 仅 p9 左 |
| `bond_*` ×5 | 0 | 只影响尾声 |
| `heardArgument` | false | p4 右,C4 消费 |
| 抉择 | 左 | 右 |
|---|---|---|
| p1 | +1 | 0 |
| p2 | +2(p1左)/ +1(p1右) | +1(p1左)/ **−1(p1右)** |
| p3 | +2 | +1 |
| p4 | 0(哄睡) | +1 + heardArgument |
| p5 | +1 | 0 |
| p6 | +2(有线索)/ +1 | 0,本通结束 |
| p7 | +2 | +1 |
| p8 | +1 | 0 |
| p9 | knot=解 | 未解 |
收播 `rep≥5` 高口碑。理论上限 12。BRIDGE 跨档播 rep_high / rep_mid / rep_low(rep_low 措辞:「今晚的口碑,还没立起来。」零起步为真)。负向结果句必须指向实际选择。
## 5. 音频三层
### 5.1 BGM(4 首,Mureka)
| 状态 | 曲目 | 切换 |
|---|---|---|
| INTRO/RING/ONAIR | `bgm/onair` | 开局淡入 800ms,全夜不切 |
| BRIDGE | `bgm/bridge` | crossfade 800ms |
| MENU | `bgm/menu` | 500ms 进,关后淡回 |
| ENDING | `bgm/ending` | p9 后淡入 1500ms |
### 5.2 SFX
onair_sting、phone_ring(循环 ≥4s 间隔,游戏层 BufferSource 持柄)、line_connect、line_drop、amb_studio、amb_rain_city、amb_station、amb_kid_room、arg_muffled、amb_street_rain、amb_cab、brake_screech、tape_static。C5 预警:h1_danger 前 2s 起 brake 渐强,与 danger 签名同窗。回执 ok/invalid/busy 走引擎合成,不靠震动。
### 5.3 Voice
| 组 | 落位 | 数量 |
|---|---|---|
| 主播 HOST | 双性别 | 21 |
| 导播 PROD | 双性别 | 82 |
| NPC ×5(老周/小鹿/糖糖/陈姐/老韩) | 平铺 + 电话滤波 | 29 |
滤波:老周 HP500/LP2800;小鹿 400/3400;糖糖 450/3000;陈姐 420/3100;老韩 300/3400。不可读则回退未滤波原声。主播/导播不滤波。
## 6. 来电音质与 Floor
Floor:SPEAKING 整链 duck;YOUR_TURN 才起等待声;RING 用铃声循环当等待声。单击跳句;滑动打断并执行。critical ≤3s 给 busy。hint/feedback 空闲才播,过期丢弃。C5 唯一 danger 点。battle 耳控不用。新手只教 turn(接听/选择)+ 可选 settle/menu 首遇一句。
## 7. 存档
```json
{
"schema": 1, "summary": "第3通·失眠的孩子 · 口碑+2 · 结局1/4",
"phase": "ONAIR", "node": "k1_asko", "rep": 2, "knot": false,
"heardArgument": true,
"bond": { "zhou": 1, "deer": 1, "kid": 0, "wife": 0, "han": 0 },
"endings": { "e2": true }, "nights": 3
}
```
summary:进行中 `第N通·<来电者> · 口碑±X · 结局K/4`;已收播 `已收播·<结局名> · 结局K/4`。
## 8. 节奏
开场 ≤10s 接到第一通;C1 ~3.5min 教学(学习期零惩罚);C2 呼吸;C3 线索音;C4 最复杂;C5 危机零死亡;签收+回响 ~3min。合计 ≈21min。操作面恒为二选一。
## 9. playtest 指针
关键路径、四结局、pendingChoice、p* 不可跳、归因真话、资产缺失续链:仍登记 `web/radio/test/playtest.mjs` 与 13 号文档。**改断言**:废除「双击重听整节点」;菜单改为左右滑+单击确认;RING/看门狗改为三档不同句;首次操作 ≤3s、首次成功 ≤10s;无效手势必有回执声(不接受只震)。