神無月サスケの波瀾万丈な日常

神無月サスケのツイッター(@ktakaki00)を補完する長文を書きます。

RPGツクールMVでDarkest Dungeon風の自動生成ダンジョンを作る

本家ダーケストダンジョンでは、クエストのクリア条件は「9割の部屋を回ること」だったり
「敵がいる部屋全てに入って敵を倒すこと」だったりしますが、
MVコラボでは、「すべての部屋を満遍なく通ること」であり、
最後に行った部屋に、ボスの前にキャンプが出来る場所へのワープホールが開けます。
さて、そんなダンジョンですが、本家に倣って、
ツクールMVのプラグインを作成して、自動生成ダンジョンにしました。
そこでツクールMVでのダンジョン自動生成の方法について説明したいと思います。

ツクールMVコラボで使われたダンジョン自動生成アルゴリズム

ツクールMVコラボでは、ダンジョンは5×5マスの中に、8〜12個の部屋を作る形式。


・オープンリストとクローズドリストを準備。
いずれも配列で、部屋IDを保存する。
部屋IDは、座標(x, y)の部屋で、y × 部屋数の幅(=5) + x になる。

1.まず始点を決める。
 - この時、上下左右、どれかの壁に隣接していることを条件としている。
 - 始点をオープンリストに入れる。
2.オープンリストに対して、それぞれ以下の処理を行う
 - この部屋から上下左右、それぞれ半分の確率で道を作る。
- 作った道の先に……
  - 既にクローズドリストに入っている部屋があったら無視。
- オープンリストに入っている部屋があったら、この部屋と廊下で繋ぐ
- いずれもないなら、新たに部屋を作り、廊下で繋ぎ、
   新しい部屋をオープンリストに加える。
- この部屋をオープンリストからはずし、クローズドリストに加える
3.クローズドリストに入った部屋の数が所定の数値(今回は8〜12)になったら中断。
 そうなるまで、2.のプロセスを繰り返す。
4.マップの完成。
- オープンリストや、それにしか繋がっていない通路など不要になったデータは即消去

上記を、ダンジョンに入る際に必ず行う。
ダンジョンを出たら、ダンジョンマップを保存するデータは破棄する。

ゲームプレイ時の部屋の作り方

動的生成されるマップをツクールMVで実現するために、
まずはそれらのマップの雛形となるものが必要である。
そこで、以下の3つの雛形マップを準備した。
(注:実際のゲームでは、マップには4種類の地形があるため、
以下のものをそれぞれの地形に合わせて3枚ずつ準備している)

  • 上下左右どこにも移動できる1画面の部屋
  • 上下方向の廊下
  • 左右方向廊下

ダンジョンはこの3つの雛形から生成されたマップだけで
構成されている(キャンプの部屋やボスの部屋は除く)。
以下に、ツクール編集画面での雛形マップを示す。



ここで大切なのは、雛形となる部屋は、四方に出入り口があることだ。
しかし実際のマップでは、通行できない方角は当然ある。
例えば、上と右だけに隣接する部屋があるマップでは、
左と下の出口を消さなければならない。
それではどうするのかを説明する。

通れない方角に処理を施す方法

簡単に言うと、部屋マップの通れない方角の出口は、
読み込まれたマップデータ($dataMap)を
フェードイン前にプラグインで直接書き換え、
壁にするという処理を行っている。
具体的には、通れない方角があれば、
その方角の壁のマップデータをコピーし、
扉部分に上書きする、というやり方を取っている。

例えば、上に通行不可能の場合、上記のように、上側の扉の部分を、
上側の他の座標の壁マップのデータを扉部分にコピーし、
通れなくしてから、マップをフェードインさせている。

廊下から、部屋からの移動の際、マップの指定方法

さて、マップは整ったが、次は移動するマップの選び方を説明する。
まず、以下の前提条件がある。

  • 廊下では両端に部屋への入り口がある
  • 部屋には通行可能な方角に廊下への出口がある

ここで部屋IDが重要になってくる(マップIDではないことに注意)。
冒頭でも書いたが、部屋は以下の式で計算される部屋IDを持っている。


座標(x, y)の部屋で、y × 部屋数の幅(=5) + x
それでは廊下はどうか。

  • 左右方向の廊下では、左の部屋の部屋IDになる
  • 上下方向の場合、上の部屋の部屋IDになる

上記から、部屋を移動するたびに、部屋IDを更新している。
そして移動の際には、部屋IDを書き換えながら、雛形マップを移動している。

オブジェ(Curio)配置について


次は、ダンジョン内にあるオブジェ(Curio)や敵の配置について解説する。
前述のダンジョン自動生成の説明では端折っていたが、
部屋がクローズドリストに追加される際に、
部屋と廊下にそれらを配置する処理を行っている。
オブジェ(Curio)や敵の数は以下のように配置している:

  • 廊下なら3つか4つ、適切な間隔を取って配置
  • 部屋には中央にひとつかふたつ置く。ふたつの場合、いずれかは敵になる。

なお、オブジェは7種類、敵シンボルの見た目は2種類だが、
廊下に配置する場合は、これら9個からランダムに配置されるため、
敵だったり、オブジェだったりする。
では置くオブジェや敵はどのように配置しているのか。
あらかじめ雛形用のダミーマップに置くことで実装している。

実行時、イベントは動的生成している

実際のゲームのプレイの際には、マップに入った際、フェードイン以前に、
部屋にあるオブジェや敵を、ダミーマップのイベントから複製し、
動的にイベントを生成している。

動的生成されたイベントのセルフスイッチについて

ゲーム中に、あるオブジェ調べたか、またはその敵を倒したかの判別には、
セルフスイッチで判断しているが、イベントは複製されていることと、
動的生成イベント専用のセルフスイッチを準備しているため、
他の同型のオブジェや敵には、影響を及ぼさない。

ダンジョン脱出時の処理

ダンジョン脱出時には、動的生成イベント用に準備されたセルフスイッチは
初期化する。ダンジョン自体がリセットされるのだから、当然である。
さもなくば、次は突然最初から空の宝箱が出てきたりしてしまう。

まとめ

以上、入るたびに形が変わるダンジョンを作る方法をかいつまんで説明しました。
もし可能なら、プラグイン素材として公開することを望む方も
少なくないでしょう。しかし、それは行わない予定です。
なぜなら、このゲームの仕様に合わせて、雛形マップIDを直接プラグイン
埋め込んでいるし、雛形マップやオブジェ(Curio)のダミーマップなど、
プラグインとして配布するには、あまりにも準備すべきものが多すぎて、
全く実用的でないからです。
よって今回のダンジョン自動生成は、あくまで概要を留めるに述べました。
将来的に何らかの形でダーケストダンジョンから独立して、
自動生成ダンジョンのプロジェクトごと公開することも検討していますが、
あまり実用性はなさそうなので見送りますが、要望が多ければ準備します。