接続されたパスを持つ手続き型2Dマップのアルゴリズム


26

解決すべき問題:すべての部屋が接続されているタイルベースのゲームのランダムな2Dダンジョンマップを生成します。

現在のソリューションよりも優れたソリューションを探しています。

私の現在の解決策は、2つのアルゴリズムを実行することです。最初の部屋ではダンジョンを生成します。2番目は、すべての部屋が接続されていることを確認します。私は他の解決策が存在するかもしれないと思っています。より高速および/または簡単など。速度は実際には問題ではありませんが、実際のコストをかけずに速度を上げることができれば、それは良いことです。さらに重要なことは、私と他の読者は、問題にアプローチして解決するさまざまな方法を学ぶことができるということです。

以下は私の現在の実装です。現在、部屋には出口がないか、2、3、または4方向に出口があります。

ダンジョンルームの生成

セットアップ:現在の部屋を左上の部屋に設定します。

  1. 部屋の有効な部屋タイプを取得します(有効な部屋タイプとは、ダンジョンの出口がなく、上の部屋と左の部屋の出口に一致する出口があるタイプです。以下の手順2のために残されました)。
  2. 部屋を置いて、x座標を1ステップ進めます。X座標がダンジョンの幅を超える場合、X座標を0に設定し、Y座標を1ステップ進めます。y座標がダンジョンの高さを超えている場合、完了です。
  3. #1から繰り返します。

次に、すべての部屋が接続されているかどうかを確認します。すべてが接続されていない場合は、2番目のアルゴリズムを実行します。接続されるまで。

すべての部屋が接続されているかどうかを確認する

セットアップ:パスを表す整数の2Dマップを作成し、エントリを「未処理」(まだ通過していない)-1に初期化します。現在のパスを追跡する開始パスインデックス整数を1に設定します。チェックする部屋のスタックに追加することにより、現在の部屋を左上の部屋に設定します。

  1. スタックにチェックするルームが含まれる場合、ポップしてルームのパスインデックスを現在のパスインデックスに設定します。スタックに部屋が含まれていない場合は、パスインデックスを増やし、まだ処理されていない部屋を取得するまで、列ごと、行ごとに進めて部屋を取得してください。部屋が見つからない場合は、完了です。
  2. 部屋の左側に出口があるかどうかを確認します。まだそこにない場合、スタックに左の部屋を追加している場合。
  3. 下方向、右方向、および上方向について手順2を繰り返します(部屋を上方向から時計回りに移動するスタックを使用しているため)。
  4. 手順1から繰り返します。
  5. パスインデックスのカウントが1より大きい場合、接続されていない部屋があります。

接続されていない部屋がある場合は、パスインデックスで部屋をグループ化し、最大のパスのインデックスを取得し、他のすべての部屋をそれらの部屋に接続します。これは進行中の作業ですが、私の(現在の、「強烈な」)計画は、部屋グループ(最初の部屋を除く)の各部屋を通過して、biggeset部屋グループへの水平または垂直パスがあるかどうかを確認することです。その場合、間に部屋を挿入/更新することにより、そこに水平/垂直パスを作成します。すすぎ、繰り返します。glyい、はい、しかしそれは視覚的なパターンの点で目立たないものなので、その意味で機能します。


1
PCG wikiで「Dungeon Generation」をチェックアウトしましたか?それはあなたの質問に答えますか?
コンガスボン14

@congusbongus確かに役に立つ読書。そのページにリンクされているドンジョンジェネレーターは素晴らしいです。ありがとう。
user1323245 14

回答:


33

私が見た中で最もよく使用されているアルゴリズムの1つは、バイナリスペースパーティション分割を使用してダンジョンを生成することです。

私が読んだ最も良い一般的な説明は、コードに入らずに実装を読者に任せることで手順を説明しているため、The Chronicles of Doryen(バックアップ目的で添付されています)にあります。

コードに関する同じテーマの2つのチュートリアルは、次の場所にあります。


BSPツリーの構築

壁のセルで満たされた長方形のダンジョンから始めます。各サブダンジョンがほぼ部屋のサイズになるまで、このダンジョンを再帰的に分割します。ダンジョンの分割はこの操作を使用します:

  • ランダムな方向を選択:水平または垂直分割
  • ランダムな位置を選択します(xは垂直、yは水平)
  • ダンジョンを2つのサブダンジョンに分割する

ここに画像の説明を入力してください

これで2つのサブダンジョンAとBができました。同じ操作を両方に適用できます。

ここに画像の説明を入力してください

分割位置を選択するときは、ダンジョンの境界に近づかないように注意する必要があります。生成された各サブダンジョン内に部屋を配置できる必要があります。最下位のサブダンジョンが生成したい部屋のおおよそのサイズになるまで繰り返します。

ここに画像の説明を入力してください

ダンジョンを構築する

次に、ツリーの各葉にランダムなサイズの部屋を作成します。もちろん、部屋は対応するサブダンジョン内に含まれている必要があります。BSPツリーのおかげで、重複する2つの部屋を持つことはできません。

ここに画像の説明を入力してください

廊下を構築するために、ツリーのすべての葉をループし、各葉をその姉妹に接続します。2つの部屋に向かい合った壁がある場合、まっすぐな廊下を使用できます。それ以外の場合は、Z字型の廊下を使用する必要があります。

ここに画像の説明を入力してください

ここで、ツリー内の1つのレベルを取得し、父のサブリージョンに対してプロセスを繰り返します。これで、2つの部屋間、または廊下と1つまたは2つの廊下間のリンクで2つのサブリージョンを接続できます。

ここに画像の説明を入力してください

最初の2つのサブダンジョンAとBを接続するまで、このプロセスを繰り返します

ここに画像の説明を入力してください


この手法がループを作成しないことは何の価値もありませんが、ランダムコリドーを追加せずにそれを回避する方法があるかどうかはわかりません。まだ非常に良い答え、+ 1
バリティ14

これは有望なスタートです。ループを追加する方法を見つける必要がありますが、私は現在の道を進むよりもむしろその問題に取り組んでいます。ありがとう。
user1323245 14

2
いいね!IDに興味があったので、ちょっとした試みをしました。ランダムを使用する場合は注意が必要です。そうしないと、あまりにも奇妙な結果になります。そして、ツリーからコリドーを構築する簡単な方法が見当たらないため、コリドーを再帰分割中に正しく処理すべきではないかと思います。とにかく興味のあるフィドルはこちらです:jsfiddle.net/gamealchemist/xt57zwb8
GameAlchemist

これは、大規模な環境での反復可能なシードされた手続き化ではやや問題があります。レベル全体を一度に生成するのであれば、この種の生成でこれまで見た中で最高の方法の1つでしょう。I 1本
そのホームレスの男

4

BSPの方法は明らかにダンジョンを生成するための最も一般的な方法であるが、それだけではないのです。

完全を期すために、私のために働いたジェネレータについて説明します。私はちょうどそれが(私の発明ではないと言うだろうので、私はこれについて読んだところ、私は覚えていませんことを認めざるを得ない古い記事によるJamisバックは非常に聞き覚え)。

部屋のある迷路

基本的な考え方は、ダンジョンはある種の部屋がある迷路だということです。したがって、このアルゴリズムの最初のステップは、迷路を生成することです:

Ellerアルゴリズムのバリエーションで生成された迷路

次のステップは、スパースにすることです(行き止まりを削除します)。

疎にする:行き止まりを削除する

ステップ3は、いくつかのループを追加する(不完全にする)ことですが、ほとんど目立たないので画像をスキップします(完璧な迷路は必要ないので、迷路生成アルゴリズムにいくつかのショートカットを追加しました。この時点でループが発生しました)。

次に、ステップ4では、孤立したセルを削除する必要があります。

孤立したセルを削除する

この時点で、廊下は完了し、部屋を追加する準備が整いました。そのために、次のことを行います。

  1. 部屋のセット(幅と高さ)を生成する
  2. 各部屋について、考えられるすべての場所を反復処理し、最適な場所を決定します。
    • 最適な場所は、条件(コリドーへの隣接など)に重みを追加して計算されます。
  3. 部屋を配置します。

これまでのところ、ダンジョンは次のようになります。 追加された部屋

最後のステップは、装飾を追加することです。

ドアと部屋番号を描く

いくつかの最終的な考え

  • Eller Algorithm簡易バージョンを使用しました。
  • 異なる迷路アルゴリズムは異なるテクスチャをもたらす可能性があります。別のアルゴリズムを好むかもしれません。たとえば、次の画像は、「Binary Tree」(対角バイアス)と「Recursive Division」(長いコリドー)アルゴリズムのバリエーションから生じるさまざまなテクスチャを示しています。 バイナリツリーと擬似再帰部

2
いい物。レベルごとに異なるアルゴリズムを使用すると、ゲームの汎用性が高まるため、さまざまな方法を探しています。
user1323245
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.