round4: H1 escape目标带实时方位 + H2 simon轮次占用预告(根治手势两义) + H3 重听账目真实化(诊断=初始发放1次vs承诺2次) + H4 input看门狗5s + H5 归因真话(gd_miss_none) + 20语音 + guide120断言全绿

This commit is contained in:
SoundGame Dev
2026-08-31 02:51:41 +08:00
parent 6be3d29b78
commit 3d37d4656d
55 changed files with 822 additions and 215 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+43 -3
View File
@@ -21,6 +21,12 @@
* 60s 无进展 L1 暗示(stuck_ask + stuck_*_1)、120s L2 明示(stuck_*_2)、
* 180s L3 带路(stuck_*_3 + 按当前坐标算路链播 nav_*,此后每 60s 重复)。
*
* round4 H1(docs/design/14-guide-layer.md「round4 v1.3」):阶段目标句
* (found_key / gd_next_fuse / fix_box)播完后,按房间图计算目标房间相对当前
* 房间的真实方位,接播 gd_room_l/r/u/d 之一(游戏反馈层全档位;目标在同一
* 房间不播;方向 = escape 移动坐标系,up/down/left/right 滑动方向即方位)。
* 引导期 g7_goal 不接(引导本身逐句带路,且引导链被 playtest 断言冻结)。
*
* 语音 id 权威清单:docs/audio/round2-voice-ids.md(已删除的 n0–n9 数字拼接链、
* hint_ 四级提示、intro/tutorial 旧开场不再引用)。震动分工:滑动/点按的识别反馈由 gesture.js 内置,本层只发语义震动
* (error/success/warning/pickup)。
@@ -406,7 +412,14 @@ export class EscapeGame extends Game {
this._progressEvent();
this.audio.play('sfx/pickup');
vibrate('pickup');
describe('voice/found_key', false);
// H1(round4):钥匙到手句后接播铁柜房方位(下一目标 = cabinet (2,1))。
this._timer(() => {
if (s !== this._session) return;
this._playVoice('voice/found_key', {
skippable: false, // 关键获得不可跳
onComplete: () => this._playGoalDir(STAGES.cabinet.target),
});
}, 800); // 先让环境音进耳朵再播描述
} else {
describe('voice/empty_2');
}
@@ -441,9 +454,12 @@ export class EscapeGame extends Game {
// G4(round3):拾取反馈链尾接下一目标句「保险丝到手。接下来,去找电箱。」
// (游戏反馈层全档位,gd_economy 先例——走游戏语音链不走向导通道)——堵上
// P2-round2 P0「保险丝到手后目标悬空:没有新指令、没有下文」。
// H1(round4):目标句播完接播目标房间方位句(P3 唯一拒因:目标无方位)。
this._playVoice('voice/unlock_cabinet', {
skippable: false, // 关键获得不可跳
onComplete: () => this._playVoice('voice/gd_next_fuse'),
onComplete: () => this._playVoice('voice/gd_next_fuse', {
onComplete: () => this._playGoalDir(STAGES.box.target),
}),
});
} else if (x === 0 && y === 0 && this.hasFuse && !this.powerOn) {
// 保险丝修电箱 -> 恢复供电(保险丝消耗)
@@ -453,7 +469,11 @@ export class EscapeGame extends Game {
this.audio.play('sfx/spark');
this.audio.play('sfx/power_on', { volume: 0.8 });
vibrate('success');
this._playVoice('voice/fix_box', { skippable: false }); // 关键获得不可跳
// H1(round4):通电目标句后接播大门方位(下一目标 = gate (2,2))。
this._playVoice('voice/fix_box', {
skippable: false, // 关键获得不可跳
onComplete: () => this._playGoalDir(STAGES.gate.target),
});
} else if (x === 2 && y === 2 && this.powerOn) {
// 通电后开大门 -> 逃脱
this._escape();
@@ -483,6 +503,26 @@ export class EscapeGame extends Game {
return 'gate';
}
/**
* H1(round4):目标房间相对当前房间的方位句(gd_room_l/r/u/d 之一)。
* 方向语义用本游戏移动坐标系:up/down/left/right 滑动方向即方位
* (y 0北..2南、x 0西..2东,向上滑 dy=-1)。斜对角只播一句,轴序与
* _navVoices 一致(先东西后南北);目标在同一房间不播(返回 null)。
*/
_roomDirVoice([tx, ty]) {
const dx = tx - this.x;
const dy = ty - this.y;
if (dx === 0 && dy === 0) return null;
if (dx !== 0) return dx < 0 ? 'voice/gd_room_l' : 'voice/gd_room_r';
return dy < 0 ? 'voice/gd_room_u' : 'voice/gd_room_d';
}
/** H1:目标句播完后接播目标房间方位句(游戏反馈层全档位,gd_next_fuse 先例)。 */
_playGoalDir(target) {
const dir = this._roomDirVoice(target);
if (dir) this._playVoice(dir);
}
// ---------- 卡关检测与三级提示 ----------
_startStuckTimer() {