Files
SoundGame/web/harness/sessions/escape.mjs
T

90 lines
4.9 KiB
JavaScript
Raw 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.
/**
* 《暗室》新手会话剧本:老玩家二周目不算——这里清空过进度走首局引导(G0-G7),
* 每步听清再做;进 PLAY 后先连撞两次墙(触发向导提前一级的卡关提示),
* 然后找到铁柜房开柜拿保险丝、照 round4 H1 的目标方位句跨四个房间修电箱、
* 再摸到大门收工(目标句后 3s 内都能听到方位句)。
*/
export function describe(game) {
switch (game.phase) {
case 'REOPEN': return '有人问我回不回来看过引导:单击直接开始,上滑重听引导';
case 'GUIDE': return game._guideBusy ? '引导在说话,照它说的做就行' : `引导第 ${game.guideStep + 1}/8 步,等我做手势`;
case 'PLAY': return `探索中,我在 (${game.x},${game.y})。四向滑挪步,单击摸一遍房间,双击用物品`;
case 'ENDING': return '逃脱了,结算播报中。播完单击再来,下滑开菜单';
case 'MENU': return '菜单里:单击切选项,双击确认,下滑关闭';
default: return '……';
}
}
export async function session(ctx, mock) {
const { game } = ctx;
// 首局:交互式引导 G0-G7(n = 引导步号 guideStep)。
// 注意:卡关轮询 interval 常驻,虚拟时钟永不"空闲"——等待一律用有界/带条件等待。
ctx.status('黑屏,只有引子的声音,先听完');
await ctx.waitCond(() => game.phase === 'GUIDE' && !game._guideBusy); // g0_intro 播完
const steps = [
{ n: 0, do: async () => { ctx.note('照引导单击了一下'); await ctx.gesture('tap'); } },
{ n: 1, do: async () => { ctx.note('随便滑了一步,有脚步声'); await ctx.gesture('up'); } },
{
n: 2,
do: async () => {
await ctx.gesture('left');
await ctx.waitVirtual(1600);
ctx.note('又滑一步,又撞墙了——墙的方位听出来了');
await ctx.gesture('right');
},
},
{ n: 3, do: async () => { ctx.note('这回往左,走通了一步'); await ctx.gesture('left'); } },
{ n: 4, do: async () => { ctx.note('往下滑,进了储物间'); await ctx.gesture('down'); } },
{ n: 5, do: async () => { ctx.note('单击摸一遍房间,摸到钥匙了'); await ctx.gesture('tap'); } },
{ n: 6, do: async () => { ctx.note('双击看了看背包'); await ctx.gesture('doubletap'); } },
];
for (const s of steps) {
await ctx.waitCond(() => game.phase === 'GUIDE' && game.guideStep === s.n && !game._guideBusy);
ctx.status(`引导第 ${s.n + 1}/8 步`);
await s.do();
await ctx.waitVirtual(800); // 缓一缓再继续(推进链由语音 onComplete 驱动)
}
// PLAY:自由探索。引导结束时我站在储物间 (0,2),手里已有钥匙
await ctx.waitCond(() => game.phase === 'PLAY');
ctx.status('引导完毕,正式开始。我在储物间');
const move = async (g, why) => {
await ctx.gesture(g);
await ctx.waitVirtual(1600); // 听脚步/环境音/描述
if (why) ctx.note(why);
};
// 先往北乱撞探探边界:两步走到 (0,0),再连撞两次北墙——向导把卡关提示提前带上来
ctx.silence(3, '辨了辨方向');
await move('up');
await move('up');
await move('up', '北边是墙,撞了一下——「那边是墙」后面还跟了句方向(向上推的是北墙)');
await move('up', '又撞了一下——听到游戏主动来问我了');
await ctx.waitVirtual(5200); // 等卡关轮询的 5s tick:连续撞墙 → 提前一级的暗示
// 去铁柜房:(0,0) → 右×2 = (2,0) → 下 = (2,1),双击用钥匙
await move('right', '往东走,风声换了个方向');
await move('right');
await move('down', '到了铁柜房,柜子锁着');
// 用钥匙 → unlock_cabinet + gd_next_fuse + gd_room_l(round4 H1:目标句带方位,
// 从铁柜房 (2,1) 看电箱房 (0,0) 在西 = 左面的房间)
await ctx.gesture('doubletap');
await ctx.waitVirtual(5600);
ctx.status('柜子开了。「保险丝到手。接下来,去找电箱。」后面还跟了一句「左面的房间。」——这回知道该往哪边摸了');
// round4 H1 剧本:照方位句跨房间去电箱房——(2,1) → 左×2 = (0,1) → 上 = (0,0)
await move('left', '照方位句往左(西)摸');
await move('left');
await move('up', '电流声越来越清晰——电箱房到了');
// 修电箱 → fix_box + gd_room_r(round4 H1:从 (0,0) 看大门 (2,2) 在东 = 右面的房间)
await ctx.gesture('doubletap');
await ctx.waitVirtual(5600);
ctx.status('电箱修好了。目标句后面照样跟着方位——「右面的房间。」大门在东边');
// 照方位句多跨两个房间摸向大门:(0,0) → 右×2 = (2,0) → 下×2 = (2,2)
await move('right', '照方位句往右(东)摸');
await move('right');
await move('down');
await move('down', '脚步声停下来——面前这间就是大门');
ctx.status('解到通电、照目标句的方位跨了四个房间摸到大门,收工');
}