你是一位遊戲工程師。請製作一款可在桌面瀏覽器玩的 3D 小遊戲:「能量核心逃脫」。 目標是交付完整、可玩、狀態正確且方便驗收的遊戲。 【交付方式】 1. 程式只交付單一 index.html,CSS 與自行撰寫的 JavaScript 全部內嵌。請完整輸出檔案內容,不得省略。 2. 使用 Three.js 0.160.0,透過 importmap 從以下 jsDelivr 網址載入: https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js 3. 除上述 Three.js 外,不使用其他外部函式庫或資源。場景只用幾何圖形與程式產生的材質,不使用外部圖片、模型、字型或音效。 4. 不需要建置、後端、帳號或付費服務。在檔案所在資料夾執行 python -m http.server,再以瀏覽器開啟 http://localhost:8000 即可遊玩。載入 CDN 需要網路。 5. 不得用 TODO、假按鈕、「其餘類推」或示意程式代替功能。 6. 程式碼後可附簡短交付說明,但不得要求另外建立程式檔案。 【遊戲內容】 1. 場景約 40×40 單位,包含地面與四周邊界、至少 6 個障礙物(不含邊界與平台)、至少 2 個高度不同的平台。 2. WASD 移動、空白鍵跳躍、P 或 Esc 切換暫停/繼續。滑鼠拖曳可水平旋轉第三人稱跟隨鏡頭。畫面須顯示操作說明。 3. W 朝鏡頭觀看方向在水平面的投影前進,S 反向,A/D 向左右移動。斜向移動速度須與直向一致。 4. 場上共有 5 顆能量核心,每顆只能收集一次。至少 1 顆必須跳上平台才能取得。收集判定須包含垂直距離,不能站在平台下方隔空收取。 5. 有 2 個敵人沿固定路線巡邏。玩家初始有 3 點生命,每次有效碰撞扣 1 點。 6. 受傷後有 1.5 秒無敵時間,以遊戲時間計算。無敵期間角色須閃爍或變色;持續接觸不得瞬間扣光生命。 7. 收集完全部核心前,出口須呈現鎖定外觀,且不能觸發勝利。收集完成後,出口變色開啟;玩家到達出口即勝利。 8. 開始遊戲後倒數 90 秒。生命歸零或倒數歸零即失敗。 9. HUD 顯示生命、已收集核心數(x/5)及剩餘秒數。 10. 提供開始畫面、暫停/繼續、重新開始,以及勝利與失敗畫面。選單期間不得開始倒數。勝敗後停止遊戲模擬,直到玩家重新開始。 【關卡與操作正確性】 1. 所有核心與出口均須能由出生點正常抵達。平台高度與間距須配合角色跳躍能力。 2. 角色不能穿過障礙物或邊界、掉穿地面,並須能站在平台上及正常離開平台。 3. 不得在空中連跳。跳躍由新的按鍵按下動作觸發,按住空白鍵不得落地後自動連跳。 4. 暫停、視窗失焦與重新開始時,清除按鍵及滑鼠拖曳狀態。恢復後,未重新按鍵不得自行移動。 5. 暫停快捷鍵須忽略鍵盤自動重複事件,避免按住按鍵時連續切換狀態。 6. 地圖配置、核心位置、出生位置與敵人巡邏起始狀態須固定。每次重新開始應得到相同的初始關卡。 【時間與狀態管理】 1. 移動、敵人、跳躍、無敵時間與倒數須依經過時間更新。可使用 delta time,或以累積時間驅動固定步長模擬。不得用畫面幀數直接決定遊戲速度。 2. 在約 30 FPS 與 60 FPS 下,移動速度、跳躍高度及倒數速度應大致一致。可使用碰撞子步進等方式避免低幀率穿透。 3. 暫停時,玩家、敵人、倒數與無敵時間全部停止。可以繼續繪製畫面,但不能推進遊戲狀態。 4. 切換到其他分頁或視窗失焦時,若原本正在遊玩,應自動進入暫停。回來後必須由玩家手動繼續。不得把選單或勝敗畫面切換成遊玩狀態。 5. 恢復時須重設時間基準,不得補算暫停期間時間、突然扣血或造成瞬移。 6. 重新開始須重設玩家位置與速度、鏡頭、敵人位置與巡邏進度、核心、生命、無敵狀態、倒數、出口及勝敗狀態。按下重新開始後直接進入 playing。 【工程要求】 1. 重新開始不得累積動畫更新鏈、事件監聽或場景物件。 2. 自行撰寫的每幀更新程式應重用暫存物件,避免反覆建立 geometry、material 與不必要的 Vector3。getState() 建立測試快照不在此限。 3. 若重建資源,須妥善處理不再使用的資源;也可重用原本場景物件。 4. 重開 10 次後,在相同遊戲階段與視角下比較,場景物件及渲染資源數量不應隨重開次數持續成長。 5. 視窗縮放後須更新畫面比例,HUD、操作說明與按鈕不得被裁切或無法操作。 6. 結構清楚、有必要註解,不追求過度架構。 【測試介面】 請在全域暴露 window.__game,至少包含: 1. renderer:實際使用的 Three.js renderer,可讀取 renderer.info。 2. getState():回傳獨立的狀態快照,格式固定為: { phase, hp, cores, timeLeft, playerPos: { x, y, z } } phase 為 'menu' | 'playing' | 'paused' | 'won' | 'lost'。 hp 為 0~3 的整數;cores 為已收集數量(0~5 的整數);timeLeft 為非負的剩餘遊戲秒數,可含小數;playerPos 為有效的玩家世界座標。 修改回傳資料不得影響遊戲內部狀態。此介面僅用於觀測,不得改變正常遊戲規則。 3. loopCount:由實際動畫迴圈啟停邏輯維護的有效動畫更新鏈數量,不得以固定常數代替。遊玩時應為 1,其他階段可以是 0 或 1,但不得因重開而增加。此數值只是輔助診斷,不能代替實際驗證。 【完成後請簡短列出】 1. 啟動方法。 2. 已實作功能與已知限制。 3. 取得平台核心的操作路線。 4. 你實際執行過的測試、測試環境與結果。 5. 尚未實際驗證的項目。 若無法執行瀏覽器,請直接說明。不要把閱讀程式、推測能運作或預期結果寫成實測通過。