自動生成・配置ルール

二分空間分割

Binary Space Partitioning / BSP

領域を繰り返し二分して部屋を配置する。

5 / 10

インタラクティブデモ

デモを準備しています…

二分空間分割

ドラッグで視点を回転、Ctrl(⌘)+ スクロールでズーム。タッチ操作は 2 本指です。

ひとことで

四角い領域を縦か横に 2 つに分けることをくり返して、小さな区画に分ける方法です。分け方を二分木として覚えておくので、「どの区画とどの区画が兄弟か」がわかります。ダンジョン生成では、各区画に部屋を 1 つ置き、兄弟の区画どうしを通路でつなぐだけで、重ならない部屋が必ずすべてつながったマップができます。

ゲームでの使いどころ

  • ダンジョン・建物の間取り:ローグライクの部屋と通路の配置。区画の大きさの下限で部屋の大きさを、分ける深さで部屋の数を調整できる。
  • 都市の区画:街を大通りで分け、さらに小道で分けて、建物の敷地を作る。
  • 描画と当たり判定:もともとは 3D の空間を平面で分けて、描く順番や見える範囲を高速に求めるための手法(『DOOM』『Quake』の BSP ツリー)。
  • テクスチャアトラスの詰め込み:大きな画像を分けながら、小さな画像を隙間なく並べる。

しくみ

  1. 分ける:今の区画の長い方の辺を、真ん中あたり(ランダムに少しずらす)で 2 つに分けます。分けた 2 つを子として木に登録します。
  2. 止める:区画の短い方の辺が「最小の大きさ × 2」より小さい、または深さが上限に達したら、それ以上分けずに葉にします。
  3. 部屋を置く:各葉の区画の中に、少し余白を取って部屋を置きます。区画どうしが重ならないので、部屋も決して重なりません。
  4. 通路でつなぐ:木の深い所から順に、各節の左の子孫の部屋と右の子孫の部屋を 1 本の通路でつなぎます。根までたどれば、全部の部屋が 1 つにつながります。

長い方の辺を分けるのは、細長い区画(廊下のような部屋)を避けるためです。分ける位置を真ん中に寄せるほど、部屋の大きさがそろいます。

実装のポイント

  • 分ける位置の範囲:最小の大きさより小さい区画ができないよう、切る位置を [min,長さ−min][\text{min}, \text{長さ} - \text{min}] に制限します。
  • 部屋の大きさのばらつき:区画いっぱいに部屋を作ると、格子のように規則的に見えます。区画の 60〜90% の範囲でランダムにすると自然です。
  • 通路の形:部屋の中心どうしを L 字に結ぶのが簡単です。ほかの部屋を横切ってもよい作りなら、そのまま通路にできます。
  • 輪を作る:木に沿ってつなぐだけだと、行き止まりの多い一本道になります。近い部屋どうしをいくつか追加でつなぐと、回り道のある遊びやすいマップになります(ドロネー分割で候補を作る方法もあります)。

つまずきやすい点

  • 格子っぽさ:分割は必ず縦横の直線なので、部屋が格子状に並んで見えやすくなります。部屋の大きさや位置のばらつきを大きくします。
  • 通路が部屋を突き抜ける:L 字の通路がほかの部屋を横切ると、意図しない出入口ができます。気になる場合は、通路を経路探索で壁を避けて引きます。
  • 深さと最小の大きさの組み合わせ:深さを大きくしても、最小の大きさで止まるので、部屋の数には上限があります。

デモで試すこと

  1. 色つきの線が、分けた位置です(色は深さ)。範囲が 2 つ、4 つ、8 つ…と分かれていく様子と、右下の分割の木の対応を確かめてください。
  2. 分け終わると、木の葉(それ以上分けなかった区画)に部屋が置かれ、深い所から順に兄弟どうしが通路でつながります。
  3. 「区画の最小の大きさ」を小さくすると部屋が増え、大きくすると大部屋が少なくなります。
  4. 「分ける位置のばらつき」を 0 にすると、部屋の大きさがそろった規則的な配置になります。

参考資料

WaveFunctionCollapse ↗

分野全体の資料で、この項目を直接扱っているとは限りません。