Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
freem
Search
Search
Appearance
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Openai/694f5245-1110-800b-b182-7c2accd50046
(section)
Add languages
Page
Discussion
English
Read
Edit
Edit source
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
Edit source
View history
General
What links here
Related changes
Special pages
Page information
Appearance
move to sidebar
hide
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
=== Assistant: 老闆我懂你說的那種「帥不到一秒就翻車」😂 === 老闆我懂你說的那種「帥不到一秒就翻車」😂 這個現象(選完機體 → saferoom 出現一下 → opening 又跑回來 → 人物卡死)幾乎可以判定是: ✅ <code>State_Init.js</code> 的 <code>init()</code> 又被呼叫了一次(或等效的 boot 流程又跑了一次) 而 init() 會做這句: <syntaxhighlight lang="js">document.getElementById('opening-screen').classList.remove('hidden'); </syntaxhighlight> 所以 opening 會「復活」,而且你的 GameLoop.update() 在 uiState === 'OPENING' 時會直接 early return,角色當然就動不了了。 ==== 在 State_Init.js 的 init() 最前面加: ==== <syntaxhighlight lang="js">console.log("[BOOT] init() called"); console.trace(); </syntaxhighlight> 你只要重現一次 bug,如果 console 出現兩次 [BOOT] init() called,就抓到了 ✅ ==== 在 State_Init.js 最上面加: ==== <syntaxhighlight lang="js">let BOOTED = false; </syntaxhighlight> 然後把 init() 開頭改成: <syntaxhighlight lang="js">function init() { if (BOOTED) { console.warn("[BOOT] init() blocked (already booted)"); return; } BOOTED = true; // 原本 init() 內容... } </syntaxhighlight> 這一刀下去,就算某個地方手滑又呼叫 init(),opening 也不會復活。 ==== 你們現在的流程很像把「開機」跟「開新局」混在一起了(Gemini 很愛這樣長歪😅)。 ==== 建議你把概念拆成兩個函式: * bootOnce():只做 DOM 建置、事件綁定、啟動 RAF loop * startNewRun(mechId):只重置 state、生成 saferoom、進入 briefing 範例骨架: <syntaxhighlight lang="js">let BOOTED = false; let rafId = null; function bootOnce() { if (BOOTED) return; BOOTED = true; // 事件綁定、抓 DOM、canvas setup... hideOpening(); // 一開始你要顯示也行,但結束後一定要 hide rafId = requestAnimationFrame(gameLoop); } function startNewRun(mechId) { // ⚠️ 這裡不要再碰 opening-screen 的 hidden state = createInitialState({ skipOpening: true }); state.player.mech = mechId; generateRoom({ kind: "SAFE" }); state.uiState = "SAFE_BRIEFING"; } </syntaxhighlight> createInitialState 也加個參數避免回到 OPENING: <syntaxhighlight lang="js">function createInitialState(opts = {}) { return { uiState: opts.skipOpening ? "MECH_SELECT" : "OPENING", flags: { openingDone: !!opts.skipOpening }, // ... }; } </syntaxhighlight> ==== 就算狀態機被弄亂,你也可以加一個「保命鎖」: ==== 只要不是 OPENING,就把 opening 畫面硬藏起來: <syntaxhighlight lang="js">function forceHideOpeningIfNotInOpening() { const el = document.getElementById("opening-screen"); if (!el) return; if (state.uiState !== "OPENING") el.classList.add("hidden"); } </syntaxhighlight> 然後在 gameLoop() 每幀 draw 之前插一行: <syntaxhighlight lang="js">forceHideOpeningIfNotInOpening(); </syntaxhighlight> 這招很粗但很有效,屬於「老闆的工程師式保命條款」🛡️ ==== 1. Deploy 按鈕或「選機體完成」的 handler 誤呼叫了 init()(或呼叫到一個內部又呼叫 init 的函式) ==== # 重新插入 script / 重新掛載 UI,導致某段 boot 流程又跑一次 # 死亡/進下一關用到同一個 reset 函式,而那個 reset 其實是 “reset to OPENING” 你只要用 console.trace() 抓到第二次 init 是從哪裡被叫,就能一槍爆頭 🔫😎 老闆你先做「✅ BOOTED 防重複」那個小 patch,通常就會立刻好。 如果你願意,把「選完機體」那段 handler(或 startNewRun / deploy 那段)貼我一下,我可以直接幫你指出是哪一行把 opening 叫回來的 😈✨
Summary:
Please note that all contributions to freem are considered to be released under the Creative Commons Attribution-ShareAlike 4.0 (see
Freem:Copyrights
for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)