← 開發日誌

M3:種子化隨機地城——房間深度鏈與模組拼裝

隨機地圖有兩種做法:開放式迷宮,或房間制。這款選了後者——理由是節奏。

為什麼是房間制,不是開放迷宮

開放迷宮容易迷路、節奏鬆散。房間制(像 Hades、以撒)把遊戲切成一個個「進房 → 戰鬥 → 選擇 → 下一房」的循環,節奏緊湊、難度好控、獎勵好給。對動作 Roguelike 來說,這個結構幾乎總是對的。

種子化 RNG:同種子、同地圖

mulberry32 這個輕量 RNG。給同一個種子,就生出一模一樣的樓層——這讓地圖可重現、可分享、可除錯(「這個 bug 在種子 12345 第三層」)。

class Rng {
  next() { /* mulberry32:一個 32-bit 狀態進、一個 [0,1) 出 */ }
  int(min, max) { ... }
  pick(arr) { ... }
  fork() { return new Rng(this.int(0, 0xffffffff)); }  // 衍生獨立子序列
}

fork() 很關鍵:每個房間拿一個從主序列衍生的獨立種子,這樣「樓層結構」和「房間內細節」的隨機互不干擾。

房間深度鏈

一層樓 = 一條「深度鏈」:depths[d] 是該深度的 1–2 個候選房間。玩家清完房後,從門選一個進入下一深度。

深度0(起點戰鬥) → 深度1 → 深度2 → … → 出口(樓梯)
                    ↓        ↓
                 [戰鬥]   [寶箱]
                 [精英]   [戰鬥]   ← 每個深度給 1-2 個選項,玩家抉擇

中段保證塞進一個寶箱房深度、一個精英房深度,剩下隨機。每三層的結構會被換成單一 BOSS 房(後面 M5 會談)。

用 KayKit 模組拼房間

房間不是一塊大地板,而是用 CC0 的 KayKit Dungeon 模組「拼」出來的:

  • 地板:tileSize × tileSize 的格子鋪滿,12% 機率換成碎石變化版
  • 四面牆:沿邊界放牆模組,北牆開 1–2 個門洞
  • 裝飾:四角柱子 + 火把(帶點光源)、隨機桶子箱子

每片牆都生一個對應的 Rapier cuboid 碰撞體;門洞則在兩側放短柱碰撞體,中間留開口。

進房鎖門、清房開門

這是房間制的節奏核心:

  1. 進房 → 門被「魔法屏障」鎖住(半透明發光面 + 一個阻擋碰撞體)
  2. EnemySpawner 按波次表刷怪
  3. 全部清空 → 發 roomCleared 事件 → 移除屏障碰撞體、隱藏屏障與木門
  4. 門上方浮標顯示「下一房是什麼類型」(戰鬥/精英/寶箱/出口)
  5. 玩家走進門 → 黑幕轉場 → 進下一房

門上的類型標示讓「選哪扇門」變成有資訊的決策,而不是賭博。

難度曲線資料化

敵人數量、種類、HP 係數全寫在 waves.ts 純資料表裡,隨樓層遞增。調平衡時只動資料、不碰邏輯——這個「資料驅動」原則貫穿整個專案(敵人、升級、掉落都是純資料表)。


現在每次爬塔都是新地圖了。下一篇讓「變強」這件事有了意義:升級系統與永久進度

← 回開發日誌立即遊玩 →

看更多開發日誌 →