ダンジョン生成
概要
Rift Survivors のダンジョンは連続階層制で構成される。1Fから15Fまで、各フロアがBSP(Binary Space Partitioning)アルゴリズムでプロシージャル生成される。ダンジョン全体は1つのシード値から決定論的に生成され、全フロアの構造が再現可能。
設計思想: チョコボの不思議なダンジョン + MCDungeons
チョコボの不思議なダンジョンの「階層を降りていく探索」に、 Minecraft Dungeonsのアクション戦闘を組み合わせる。 各フロアはBSPで自動生成されるが、5F/10F/15Fのボスフロアは固定レイアウト。
階層構成
フロアごとのパラメータ
| フロア | 敵ステータス倍率 | 敵数 | トラップ数 | モンスターハウス確率 | ドロップ品質 |
|---|---|---|---|---|---|
| 1F | 1.0x | 20 | 0 | 0% | 1.0x |
| 2F | 1.1x | 22 | 1 | 5% | 1.0x |
| 3F | 1.2x | 25 | 2 | 10% | 1.0x |
| 4F | 1.3x | 28 | 3 | 15% | 1.0x |
| 5F | — | ボス戦 | 0 | 0% | ボス報酬 |
| 6F | 1.5x | 25 | 2 | 10% | 2.0x |
| 7F | 1.6x | 28 | 3 | 15% | 2.0x |
| 8F | 1.8x | 30 | 4 | 20% | 2.0x |
| 9F | 2.0x | 32 | 5 | 25% | 2.0x |
| 10F | — | ボス戦 | 0 | 0% | ボス報酬(2x) |
| 11F | 2.2x | 30 | 4 | 20% | 3.0x |
| 12F | 2.5x | 32 | 5 | 25% | 3.0x |
| 13F | 2.8x | 35 | 6 | 30% | 3.0x |
| 14F | 3.0x | 38 | 7 | 35% | 3.0x |
| 15F | — | ボス戦 | 0 | 0% | ボス報酬(3x) |
フロア生成アルゴリズム: BSP(Binary Space Partitioning)
アルゴリズム全体フロー
BSP分割の詳細
分割パラメータ
| パラメータ | 値 | 説明 |
|---|---|---|
| 全体サイズ | 80×80 units | 1フロアの大きさ |
| 最大分割回数 | 5回 | 再帰の深さ上限 |
| 最小区画サイズ | 10×10 units | これ以下は分割しない |
| 分割比率 | 0.4〜0.6 | 分割位置のランダム幅 |
| 分割方向 | 交互(横→縦→横...) | 偏りを防ぐ |
分割アルゴリズム(疑似コード)
interface BSPNode {
x: number; y: number;
width: number; height: number;
left?: BSPNode;
right?: BSPNode;
room?: Room;
}
function splitBSP(node: BSPNode, depth: number, rng: SeededRNG): void {
if (depth >= MAX_DEPTH) return;
if (node.width < MIN_SIZE * 2 && node.height < MIN_SIZE * 2) return;
const splitHorizontally = node.width < node.height
? true
: node.width > node.height
? false
: rng.next() > 0.5;
if (splitHorizontally) {
const splitY = node.y + lerp(node.height * 0.4, node.height * 0.6, rng.next());
node.left = { x: node.x, y: node.y, width: node.width, height: splitY - node.y };
node.right = { x: node.x, y: splitY, width: node.width, height: node.y + node.height - splitY };
} else {
const splitX = node.x + lerp(node.width * 0.4, node.width * 0.6, rng.next());
node.left = { x: node.x, y: node.y, width: splitX - node.x, height: node.height };
node.right = { x: splitX, y: node.y, width: node.x + node.width - splitX, height: node.height };
}
splitBSP(node.left, depth + 1, rng);
splitBSP(node.right, depth + 1, rng);
}部屋配置ルール
各リーフノード内にランダムサイズの部屋を配置する。
部屋の幅 = random(区画幅 × 0.5, 区画幅 × 0.9)
部屋の高さ = random(区画高さ × 0.5, 区画高さ × 0.9)
部屋の位置 = 区画内でランダムにオフセット(壁から最低1unit離す)| パラメータ | 値 |
|---|---|
| 部屋最小サイズ | 6×6 units |
| 部屋最大サイズ | 区画の90% |
| 壁厚 | 0.5 units |
| 生成される部屋数 | 8〜16部屋(分割回数に依存) |
部屋タイプ
部屋タイプ一覧
| タイプ | 出現数 | 説明 | 視覚的特徴 |
|---|---|---|---|
| スタート部屋 | 1 | プレイヤーの初期位置(1Fのみ)/ 階段出口 | 明るいネオン照明、安全地帯 |
| 戦闘部屋 | 4〜8 | 敵がスポーンする主要エリア | 暗い照明、赤い警告ライン |
| エリートアリーナ | 1〜2 | エリート敵が出現する大部屋 | 紫のオーラ、広い空間 |
| 宝物部屋 | 1〜2 | アイテムの宝箱(未識別チップ含む) | 金色のライティング |
| 回復部屋 | 1〜2 | HP回復+バフアイテム | 緑色のライティング |
| 階段部屋 | 1 | 次フロアへの階段が配置 | シアン色のリフトエフェクト |
| モンスターハウス | 0〜1 | リフトサージ発生部屋 | 入室まで通常部屋に見える |
部屋タイプの配置ルール
距離計算: 部屋間の距離はBSPツリー上のホップ数(部屋中心間のマンハッタン距離ではなく、通路を通った実際の経路長)で算出する。
階段オブジェクト
各フロアには次のフロアに進むための階段が1つ配置される。
| パラメータ | 値 |
|---|---|
| 配置位置 | スタート部屋から最遠の部屋 |
| サイズ | 2×2 units |
| 視覚エフェクト | シアン色の下向き渦 + パーティクル |
| インタラクション | Fキーで次フロアへ移動 |
| 移動演出 | 0.5秒のフェードアウト → 次フロアロード → フェードイン |
| 条件 | なし(いつでも降りられる。全敵撃破は不要) |
設計意図
トルネコ/チョコボと同様、階段はいつでも使える。 敵が多すぎる場合は戦闘を避けて階段を目指す「逃げプレイ」も有効な戦略。 ただしレベルが足りないままボスフロアに到達すると苦戦する。
ボスフロアレイアウト(固定)
5F/10F/15Fのボスフロアは、BSP生成ではなく固定レイアウトを使用する。
┌────────────────────────────────────────────────────┐
│ │
│ ┌──────────┐ ┌────────────────────────────┐ │
│ │ │ │ │ │
│ │ 前室 │────│ ボスアリーナ │ │
│ │ 回復 │ゲート│ │ │
│ │ アイテム │ │ [ボス] │ │
│ │ │ │ │ │
│ │ [入口] │ │ 撃破後: │ │
│ │ ↑階段 │ │ [帰還ポータル] [次の階段] │ │
│ └──────────┘ └────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────┘| パラメータ | 5Fボスフロア | 10Fボスフロア | 15Fボスフロア |
|---|---|---|---|
| 前室サイズ | 10×10 units | 10×10 units | 10×10 units |
| アリーナサイズ | 20×20 units | 25×25 units | 30×30 units |
| ゲート仕様 | 入場後閉鎖 | 入場後閉鎖 | 入場後閉鎖 |
| ボス撃破後 | 帰還ポータル + 6F階段 | 帰還ポータル + 11F階段 | 帰還ポータル(最終) |
トラップ(グリッチトラップ)
不思議のダンジョン要素: グリッチトラップ
チョコボの不思議なダンジョンのワナ要素を取り入れる。 床に不可視のトラップが配置され、踏むと様々な効果が発動する。 「???チップ」(未識別アイテム)と同様、不確定要素としてプレイに緊張感を与える。
トラップ一覧
| トラップ名 | 効果 | ダメージ/影響 | 視覚予兆 |
|---|---|---|---|
| データリーク | HP減少 | 最大HPの15%ダメージ | なし(踏むまで不可視) |
| スタンパルス | 一定時間行動不能 | 2秒間スタン | なし |
| ワープホール | ランダムな部屋に転送 | ダメージなし | なし |
| アラームトラップ | 敵を追加スポーン | 周囲に敵8体スポーン | なし |
| デバフフィールド | ステータス低下 | ATK -30% / 30秒 | なし |
| コラプトトラップ | 持ちアイテム1つが呪い化 | ランダムで呪い付与 | なし |
トラップの配置ルール
トラップ配置数 = フロア番号に応じた数(上記テーブル参照)
配置位置 = 通路または部屋内のランダムな床タイル
配置禁止 = スタート部屋、階段の直近2タイル、回復部屋
発動条件 = プレイヤーが踏む(敵は発動しない)
一度発動したトラップは可視化され、再発動しないトラップへの対策
- スキル「トラップスキャン」を選択すると、半径3unit以内のトラップが可視化される
- 一部の武器ボーナス「トラップ耐性」でトラップダメージを軽減可能
- 踏んだトラップは可視化されるため、リベンジ時は同じ場所を避けられる
モンスターハウス(リフトサージ)
不思議のダンジョン要素: リフトサージ
トルネコの「モンスターハウス」に相当する要素。 一見普通の部屋に入ると、突然大量の敵が出現する。 危険だが、全滅させれば大量の報酬を獲得できる。
リフトサージの仕様
| パラメータ | 値 |
|---|---|
| 出現確率 | フロアごとに異なる(上記テーブル参照) |
| 出現数/フロア | 最大1部屋 |
| 発動条件 | プレイヤーが部屋に入室 |
| 出現敵数 | 50〜80体(フロア深度で増加) |
| 部屋封鎖 | 発動後、部屋の全出入口が封鎖(全敵撃破で解除) |
| 敵の種類 | そのフロア帯の通常敵 + エリート1〜2体 |
| 予兆 | なし(入室するまで通常部屋と区別不能) |
リフトサージ報酬
| 報酬 | 量 |
|---|---|
| EXP | 通常フロアの3〜5倍 |
| アイテムドロップ | 5〜8個(高品質) |
| ???チップ | 1〜3個 |
| レア武器 | 1個(Rare以上確定) |
リフトサージの危険性
リフトサージは回避できない(入室するまでわからない)。 レベルが低い状態で遭遇すると非常に危険。 逆にレベルが十分なら大量のEXPとアイテムを稼ぐチャンス。 リベンジ時は同じ部屋にリフトサージがあることがわかるため、対策を立てられる。
通路生成
BSPツリーの各内部ノードにおいて、左右の子ノードに属する部屋同士を通路で接続する。
通路パラメータ
| パラメータ | 値 |
|---|---|
| 通路幅 | 2.0 units |
| 通路形状 | L字型(水平→垂直 or 垂直→水平) |
| 接続方式 | 各部屋の最寄りの辺の中点を結ぶ |
通路生成アルゴリズム
function connectRooms(roomA: Room, roomB: Room, rng: SeededRNG): Corridor {
const pointA = roomA.center;
const pointB = roomB.center;
if (rng.next() > 0.5) {
return [
{ x1: pointA.x, y1: pointA.y, x2: pointB.x, y2: pointA.y },
{ x1: pointB.x, y1: pointA.y, x2: pointB.x, y2: pointB.y }
];
} else {
return [
{ x1: pointA.x, y1: pointA.y, x2: pointA.x, y2: pointB.y },
{ x1: pointA.x, y1: pointB.y, x2: pointB.x, y2: pointB.y }
];
}
}環境バリエーション
テーマ
ダンジョンのビジュアルテーマはフロア帯で変化する。
| テーマ | 適用フロア | 色調 | 環境ハザード |
|---|---|---|---|
| データグリッド | 1F〜5F | シアン / ブルー | なし(序盤は安全) |
| ネオンアーケード | 6F〜10F | ピンク / マゼンタ | 電撃トラップ(床が周期的に通電) |
| グリッチコア | 11F〜15F | パープル / グリーン | 不安定床(一定時間で崩壊) |
テーマ変化の意図
フロア帯ごとにビジュアルが変わることで、深度の進行を視覚的に体感できる。 「色が変わった = 危険度が上がった」という直感的なフィードバック。
環境ハザード
| ハザード | ダメージ | 発動間隔 | 予兆 | 出現フロア |
|---|---|---|---|---|
| 電撃トラップ | HP 5%/秒 | 8秒ON/4秒OFF | 床の点滅(2秒前) | 6F〜10F |
| 不安定床 | 即死(落下) | プレイヤーが乗って3秒後 | 亀裂のひび割れ(1秒前) | 11F〜15F |
環境オブジェクト
| オブジェクト | 機能 | 破壊可能 |
|---|---|---|
| データモニュメント | 触れるとEXPジェム(大)ドロップ | Yes |
| エネルギーピラー | 一定時間ごとにHP回復フィールド展開 | No |
| 破壊可能な壁 | 攻撃で破壊、ショートカット生成 | Yes(HP 50) |
| 爆発バレル | 攻撃で爆発(半径2.0, 50ダメージ, 敵味方問わず) | Yes(HP 1) |
ミニマップ
ダンジョン探索中はHUD上にミニマップを表示する。
| 表示要素 | アイコン/色 |
|---|---|
| 現在位置 | 白い矢印 |
| 訪問済み部屋 | 薄い灰色 |
| 未訪問部屋 | 非表示 |
| 通路 | 薄い灰色のライン |
| 階段 | シアンの下矢印アイコン |
| 宝物部屋 | 金色のアイコン |
| 帰還ポータル(ボス撃破後) | シアンのアイコン |
| 敵(ミニマップ内) | 赤い点 |
| トラップ(発見済み) | 黄色の×マーク |
ミニマップサイズ: 画面右上 150×150px。M キーで全体マップ表示に切り替え。
シード値によるリプレイ可能な生成
シード値の役割
ダンジョン全体(全15フロア)は1つのシード値から決定論的に生成される。 各フロアの生成には シード値 + フロア番号 を入力として使用する。
interface DungeonSeed {
seed: number; // 乱数シード値(ダンジョン全体)
}
function generateFloor(seed: number, floor: number): Floor {
// フロアごとのサブシードを生成
const floorSeed = hash(seed, floor);
const rng = createSeededRNG(floorSeed);
if (isBossFloor(floor)) {
return generateBossFloor(floor, rng);
}
// BSP分割、部屋配置、敵配置、トラップ配置、
// モンスターハウス判定を全て rng から生成
return generateNormalFloor(floor, rng);
}
function isBossFloor(floor: number): boolean {
return floor === 5 || floor === 10 || floor === 15;
}全フロアの決定論的生成
| 要素 | シード依存 |
|---|---|
| 各フロアのマップ構造 | シード + フロア番号から決定 |
| 敵の種類・配置 | シード + フロア番号から決定 |
| ボスの種類・弱点 | シードから決定(サイクル固定) |
| トラップの位置 | シード + フロア番号から決定 |
| モンスターハウスの有無・位置 | シード + フロア番号から決定 |
| アイテム配置 | シード + フロア番号から決定 |
| ドロップテーブル | 同じ(乱数は戦闘時に再生成) |
| ボスヒントの配置 | シード + フロア番号から決定 |
リベンジとの連携
死亡時にシード値をlocalStorageに保存。リベンジポータルから再挑戦すると 同じシード値で全フロアが再現される。マップ構造、トラップ位置、 モンスターハウスの場所が全て同じなので、前回の経験を活かした攻略が可能。
パフォーマンス考慮
Three.jsでの実装指針
| 項目 | 方針 |
|---|---|
| 床・壁のメッシュ | タイルベースのInstancedMesh で一括描画 |
| 通路 | 同一マテリアルのメッシュを結合(BufferGeometry merge) |
| 視野外の部屋 | Frustum Culling(Three.js標準) |
| LOD | プレイヤーから遠い部屋のオブジェクトを簡略化 |
| 描画上限 | Draw Call 目標: 100以下 |
| フロア遷移 | 現フロアのみメモリに保持。次フロア移動時に前フロアを破棄 |
メモリ目安
| 要素 | サイズ見込み |
|---|---|
| BSPツリーデータ(1フロア) | ~2KB |
| 部屋ジオメトリ(1フロア) | ~500KB |
| テクスチャ | ~2MB(環境テーマ1種分) |
| 合計(1フロア) | ~3MB |
| ボスフロア(固定レイアウト) | ~1MB |