diff --git a/.workbuddy/memory/2026-10-22.md b/.workbuddy/memory/2026-10-22.md index 5becc7e..34247fa 100644 --- a/.workbuddy/memory/2026-10-22.md +++ b/.workbuddy/memory/2026-10-22.md @@ -94,3 +94,13 @@ - `buildData()` 导出 grid 时把每格 `^` 按 `props.dir` 翻译成 `^ v < >`;`hydrate()` 反向把 `^ v < >` 统一还原成 `^` 并写 `props.dir`。往返一致。 - `index.html`:`editor-tip` 改为说明「不会覆盖已有方块」「刺只有一个、方向在右侧属性面板调」。 - 验证:Node 桩冒烟(`/tmp/ed_noclip_spike.mjs`,13 断言全过:不覆盖/擦除/橡皮、buildData 四向翻译、renderProps('^') 不抛、hydrate 往返一致);`death/map/check/solve/smoke/save/key/dom-smoke/ice` 九套全绿。 + +## 暂停菜单末项:试玩时改为「返回编辑器」 +- 需求:试玩界面暂停菜单的最后一项从「返回关卡选择」改成「返回编辑器」,跳转功能同步改。 +- 只在「从编辑器试玩」时生效,普通游玩(含从关卡选择启动自制关)仍是「返回关卡选择」,不影响原流程。 +- `js/main.js`: + - `G` 新增 `fromEditor` 标志;`Editor.init` 的 `startLevel` 回调置 `true`,`UI.init` 的 `play` 回调置 `false`(`restart`/`retry` 不重置,保持来源)。 + - 新增 `toEditor()`(=`editor` 动作原逻辑:state=editor + show scr-editor + `Editor.open()`,因 faces 已存在只是重渲染,地图不丢)。 + - `pause()` 里按 `G.fromEditor` 改 `#scr-pause [data-act="quit"]` 的 textContent;`UI.init` 的 `quit` 改为 `() => (G.fromEditor ? toEditor() : toLevels())`。 +- 结算屏(scr-result)的 quit 未动,仍为「关卡选择」——用户只要求暂停界面。 +- 验证:Node 桩冒烟(`/tmp/ed_pause_quit.mjs`,5 断言:两种来源标签切换、quit 两种跳转、从关卡选择启动自制关复位 fromEditor);`death/map/check/solve/smoke/save/key/dom-smoke/ice` 九套全绿。 diff --git a/js/main.js b/js/main.js index a4116e2..1944641 100644 --- a/js/main.js +++ b/js/main.js @@ -33,6 +33,7 @@ const G = { level: null, player: null, cam: null, data: null, idx: -1, map: null, face: 0, // 多面地图:map=各面 Level 数组,face=当前面下标 + fromEditor: false, // 是否从编辑器「试玩」进入(决定暂停菜单末项去向) deaths: 0, ms: 0, hudTick: 0, time: 0, lastLevelId: null, @@ -168,7 +169,16 @@ function nextLevel() { } function toLevels() { G.state = 'menu'; UI.show('scr-levels'); Touch.hide(); } function toTitle() { G.state = 'menu'; UI.show('scr-title'); Touch.hide(); } -function pause() { if (G.state === 'playing') { G.state = 'paused'; UI.show('scr-pause'); Touch.hide(); } } +function toEditor() { G.state = 'editor'; UI.show('scr-editor'); Touch.hide(); Editor.open(); } +function pause() { + if (G.state !== 'playing') return; + G.state = 'paused'; + // 暂停菜单末项:从编辑器试玩进来 → 「返回编辑器」;否则 → 「返回关卡选择」 + const q = document.querySelector('#scr-pause [data-act="quit"]'); + if (q) q.textContent = G.fromEditor ? '返回编辑器' : '返回关卡选择'; + UI.show('scr-pause'); + Touch.hide(); +} function resume() { if (G.state === 'paused') { G.state = 'playing'; UI.showGame(); showTouch(); } } // ---------------- 更新 ---------------- @@ -277,14 +287,14 @@ Save.load(); Audio2.enabled = Save.data.audio !== false; UI.init({ - play: (lv) => startLevel(lv, lv.builtin === false ? -1 : (lv.index ?? -1)), + play: (lv) => { G.fromEditor = false; startLevel(lv, lv.builtin === false ? -1 : (lv.index ?? -1)); }, levels: toLevels, help: () => UI.show('scr-help'), - editor: () => { G.state = 'editor'; UI.show('scr-editor'); Touch.hide(); Editor.open(); }, + editor: toEditor, back: toTitle, resume, restart: () => { restart(); }, - quit: toLevels, + quit: () => (G.fromEditor ? toEditor() : toLevels()), retry: () => startLevel(G.data, G.idx), next: nextLevel, wipe: () => { @@ -293,7 +303,7 @@ UI.init({ }); Editor.init({ - startLevel: (data) => startLevel(data, -1), + startLevel: (data) => { G.fromEditor = true; startLevel(data, -1); }, refresh: () => UI.renderLevels(), });