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
+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() {