見出し画像

【ゲーム制作】飽きないランダム生成ダンジョンのルール作りを考える

以前の記事では、私が『ピクミン2』の地下洞窟に感じている魅力について書きました。

今回はもう少し仕組みの側へ踏み込み、あの地下洞窟がどのようなルールで作られているのか、そして、その考え方を現在制作中の『スクラップダイバー』へどう取り入れたいのかを書いてみます。

『ピクミン2』の洞窟生成には細かな処理が数多くあります。すべてを書こうとするとキリがないため、今回は私が魅力に感じた部分と、自分のゲームへ取り入れたい部分に絞ります。

なお、『ピクミン2』の詳しい生成方法は、任天堂から公式に公開されたものではありません。

この記事では、ゲーム内データの解析や洞窟生成を再現した非公式ツールなどをもとに、ネット上で公開されている情報を参考にしています。実際の処理とは異なる可能性があることをご了承ください。

詳しい方がいましたら、コメントなどで訂正していただけるとありがたいです。


『ピクミン2』のランダム生成ダンジョン

部屋を一から作るのではなく、用意された部品をつなげる

ランダムダンジョンには、床や壁をマス単位で生成して、部屋や通路を作る方法があります。

一方で、『ピクミン2』の地下洞窟は、床や壁を一つずつ並べて作られているわけではありません。

あらかじめ制作者の手で作られた、部屋、通路、袋小路の3種類の地形パーツをつなぎ合わせることで、一つの階層を作っています。
つまり、地形パーツそのものは人が設計し、その組み合わせや接続の仕方をゲーム側が毎回変えているわけです。 

左から部屋、通路、袋小路

この方式なら、部屋の中に柱を置いたり、高低差を作ったり、特徴的な形にしたりと、制作者の手によるレベルデザインを残せます。
そのうえで、どの部屋が選ばれ、どの方向へつながるかが毎回変化するため、同じ階層でも異なる地形になります。

地形パーツには配置候補が設定されている

それぞれの地形パーツには、地形の形だけでなく、何をどこへ置けるのかという候補地点も設定されています。

たとえば、次のようなものです。

  • スタートスポット:その階層に入ったとき、プレイヤーたちが降りてくる位置の候補です。 一つの部屋に複数のスタートスポットが用意されている場合、実際にどこから始まるかは生成時に選ばれます。

  •  穴スポット:次の階層へ進むための穴を置ける位置の候補です。 

  • 接続口:部屋、通路、袋小路など、別の地形パーツをつなぐ場所です。 接続口同士の向きを合わせて地形パーツを設置することで、地形を広げていきます。

  •  敵スポット:敵を配置できる位置の候補です。 敵の強さや出現方法によって、候補地点にもいくつかの分類があるようです。 

  • お宝スポット:お宝を配置できる位置の候補です。

このように、敵やお宝を完成した地形の好きな場所へ無作為に置くのではなく、各地形パーツに用意された候補の中から配置場所を選びます。
制作者が「ここなら敵を置いても遊べる」「ここならお宝を回収できる」と考えた場所だけを候補にすることで、ランダム生成でありながらゲームとして成立する範囲を保っています。

地形が作られるまで

まず、階層ごとに、そこで使用できる地形パーツの種類が設定されています。
土でできた洞窟なら土の部屋や通路を使い、玩具のような空間ならそれに合った地形パーツを使います。
使用する部品を階層ごとに限定することで、ランダム生成でありながら、その階層らしい見た目や雰囲気を保っています。

また、階層ごとに、生成する部屋の数も設定されています。
部屋数が少なければ小さくまとまった階層になり、部屋数が多ければ探索範囲の広い階層になります。
この二つの設定をもとに、地形の生成が始まります。

  • 最初の部屋を置く:まず、「スタートスポット」を持つ部屋を一つ配置します。
    ただし、この時点では実際のスタート位置まで決まるわけではありません。
    部屋の中に用意された複数のスタートスポットのうち、どこを使うかは、地形が完成した後に選ばれます。

  • 接続口へ新しい部屋をつなげる: 最初の部屋を置いた後は、まだ使われていない接続口へ、次の部屋をつなげようとします。
    接続口の向きに合う部屋を選び、回転させながら配置を試します。
    ただし、新しい部屋が、「すでに置かれている地形と重なる」「接続口の向きが合わない」「正しい位置へ置けない」といった場合には、その部屋を配置できません。
    その場合は、別の部屋や向きを試します。
    また、同じ形の部屋ばかりが続かないように、選ばれる地形パーツにも調整が入っているようです。

  • 部屋を置けなければ通路を置く: 接続口へ部屋を直接置けない場合は、代わりに通路を置きます。
    通路を挟むことで、現在の接続口から少し離れた場所へ新しい接続口を作れます。
    その先でもう一度部屋を置くことで、既存の地形を避けながら、別の方向へ階層を広げられます。

  • 通路も置けなければ袋小路を置く: 部屋も通路も配置できない場合は、接続口へ袋小路を置きます。
    袋小路を置いた方向からは、それ以上地形を広げません。

つまり、地形を広げるときには、大まかに次の順番で配置を試します。

「接続口へ部屋を置く」
「部屋を置けなければ通路を置く」
「通路も置けなければ袋小路で閉じる」

この処理を、その階層に設定された部屋数へ達するまで繰り返します。

  • 残った接続口を閉じる:必要な数の部屋を置き終えた後は、まだ使用されていない接続口へ袋小路を配置していきます。
    また、配置された袋小路が、すでに存在する別の地形パーツへ接触した場合には、そこが新しい通り道としてつながることもあるようです。
    そのため、単純に一本の道から枝分かれするだけでなく、別々に伸びた道が途中でつながり、回り道ができる場合もあります。

これで、敵やお宝を置く前の地形が完成します。

大きな部屋2つのみが設定されている階層の場合の生成例

地形が完成すると、次にスタート地点、次の階層への穴、敵、お宝などを配置していきます。

ここで使われるのが、「スコア」と呼ばれる評価値です。
スコアは、生成された地形の中で、
「どの部屋がスタート地点に近いのか」
「どの部屋が階層の奥にあるのか」
「そこへ向かう道がどれくらい危険なのか」
を、ゲーム側が判断するための値です。

主に次のような要素が関係しているようです。

1. スタート部屋から対象の地形パーツまでの道の長さ

2. その道中に配置されている敵の数や種類

3. 対象がスタート地点と同じ部屋かどうか

基本的には、スタート地点から遠く、そこへ向かうまでの危険が大きい場所ほど、スコアが高くなります。
このスコアを使って、次の階層への穴やお宝をどこへ置くか決めていきます。

スタート地点、穴、敵、お宝を順番に置く

 1. スタート地点を決める:まず、最初に置かれた部屋のスタートスポットから、実際のスタート地点が選ばれます。
同じ部屋が最初に選ばれても、部屋の中に複数の候補があれば、開始位置が変わる可能性があります。

 2. 次の階層への穴を置く:次に、次の階層へ進むための穴を配置します。 
この段階では、まだ敵が生成されていません。 
そのため、敵による危険度は計算に入れず、主にスタート地点からの距離をもとに各地形パーツのスコアを計算します。
そして、スコアが高い、つまりスタート地点から遠い場所にある穴スポットの中から、実際に穴を置く場所が選ばれます。 
これによって、階層へ入ってすぐ穴が見つかるのではなく、ある程度奥まで探索する必要が生まれます。

 3. 敵を配置する: 穴を置いた後は、敵を配置します。
敵の配置候補が次のような名称で分類されているようです。

「Easy Enemy」
小さくて弱い敵を置くための候補です。
一つの場所に、同じ敵が複数まとめて生成されることもあります。

「Hard Enemy」
一般的な敵を置くための候補です。
名前は「Hard」ですが、必ずしも強敵だけを意味するわけではなく、通常の敵が分類されることもあるようです。

「Special Enemy」
特殊な場所や方法で出現する敵を置くための候補です。
通常とは違う出現方法を持つ敵や、厄介な仕掛けを持つ敵などが分類されます。

「DoorEnemy」
地形パーツ同士の接続口付近へ、敵や障害物を置くための候補です。
進路を塞ぐ大型の敵や、壊さなければ進めない障害物などが置かれます。

階層ごとに、
「どの敵を出すか」
「その敵をどの分類として扱うか」
「最大で何体まで出すか」
などが設定されています。

その設定に従い、敵スポットの中から配置場所が選ばれます。

また、スタート地点のすぐ近くには敵が置かれにくいようになっています。
完全な安全が保証されているわけではありませんが、階層へ入った瞬間にいきなり囲まれるような状況を防ぐための調整だと思われます。

4. 敵を置いた後、スコアを計算し直す:敵の配置が終わると、各地形パーツのスコアをもう一度計算します。
 最初に穴を置いたときは、まだ敵がいなかったため、主にスタート地点からの距離だけを見ていました。
 今回は、そこへ向かう道中にどの敵が置かれたのかも計算へ入ります。 
同じ距離にある二つの部屋でも、片方の道に強い敵が多く配置されていれば、そちらの方が危険な場所として高く評価されます。 

5. お宝を配置する: 最後に、お宝スポットの中から、お宝を置く場所を選びます。
お宝は、スコアの高い場所ほど配置候補になりやすくなります。

つまり、
「スタート地点から遠い」
「そこへ向かう道が長い」
「道中に敵が多い」
「危険な敵を突破する必要がある」
といった場所ほど、報酬を置く場所として選ばれやすくなります。

私が特に面白いと感じたのは、この部分です。

お宝を完全に無作為な場所へ置くのではなく、先に地形と敵を生成し、その結果を見てから、お宝にふさわしい場所を決めています。

「遠くまで探索する」
「危険な敵を突破する」
「その先で価値のあるお宝を見つける」
という流れが、固定されたステージではなく、毎回生成された状況の中から生まれます。

この後に、袋小路に置かれるアイテム(卵や花)や、接続口を塞ぐ壊せる壁などが配置されるようです。

それらにも細かな生成ルールがありますが、今回は自分のゲームへ取り入れたい部分から少し離れるため、省略します。

私が魅力を感じた生成ルール

『ピクミン2』の洞窟生成を調べて、私が特に面白いと感じたのは、次の四つです。

制作者が作った地形パーツを組み合わせる

すべてをゲーム側にランダムで作らせるのではなく、部屋や通路そのものは制作者が設計しています。
制作者の手で作った地形の特徴を残しながら、組み合わせによって毎回違う階層を作れます。

配置した敵からのスコアの算出

最初に地形を完成させ、その後で敵を置きます。
同じ地形パーツが選ばれても、敵の種類や位置が変われば、そこで必要になる行動も変わります。
これにより、危険な場所の先に報酬が置かれるという関係を、ランダム生成の中でも作れます。

完全な無作為にはしない

地形パーツ、配置スポット、部屋数、敵の最大数、スコアなど、制作者側が決めた多くの制限があります。

乱数だけで多くの事を決めるのではなく、
「面白い状況が生まれる範囲を制作者が作り、その中で組み合わせがランダムに変わる」
という設計になっています。

私が『スクラップダイバー』へ取り入れたいのも、この考え方です。

自作ローグライク『スクラップダイバー』へ取り入れたい要素

ここからは、調べた仕組みを、現在制作中のローグライク『スクラップダイバー』へどう取り入れるかを考えていることを書いていきます。

現在制作中のゲームの主人公
半分が生身で、半分が機械のサイボーグ。
機械だらけの地下ダンジョンへ潜り、敵を避けたり戦ったりしながら、スクラップを回収する。

現在は本編へ地形生成を組み込む前に、ダンジョンの生成ルールだけを確認する小さなGodotプロジェクトを作っています。

キャラクター操作や戦闘はなく、Rキーを押すたびに、新しい地形が生成されるだけの簡単なものです。

良いランダム生成ルールが作られるか確認するだけのプロジェクト

接続口から地形を広げる

最初に試した方法では、盤面の中へ長方形の部屋を複数置き、その中心同士を通路で結んでいました。
一応ランダムダンジョンにはなりましたが、私が作りたかったものとは少し違いました。
部屋が先に独立して置かれ、その後から通路で無理やり結ばれているように見えたからです。

そこで、部屋や通路を接続口から一つずつ広げる方式にしました。

最初に部屋を一つ置きます。

その部屋にある未使用の接続口を選び、そこへ通路をつなげます。

通路の先へ新しい部屋を置き、増えた接続口から、さらに別の地形を広げていきます。

新しい地形が、
「すでにある地形と重なる」
「盤面の外へ出る」
「接続する場所以外で別の地形へ触れる」
といった場合には、その配置を行いません。

別の部屋、通路、向きを試し、それでも置けない接続口は閉じます。

階層全体の規模も変える

最初は、毎回7個から8個の部屋を生成するようにしていました。

しかし、部屋の位置や形が変わっても、毎回ほぼ同じ数の部屋が並ぶため、階層全体の印象が似ていました。

私が作りたいのは、配置だけでなく、階層の規模そのものも大きく変わるダンジョンです。

そこで現在は、階層を生成するときに、最初に全体の傾向を決めています。

たとえば、
「小部屋が多く並ぶ階層」
「小部屋から大部屋まで混ざる階層」
「大部屋が少数だけある階層」
「特大部屋が一つだけある階層」
「特大部屋を中心に枝道が伸びる階層」
などです。

すべての階層を平均的な広さに整えるのではなく、次の階層へ進んだときに、
「今回は狭い部屋が多い」
「今回は大きな空間が中心になっている」
と感じられる変化を作りたいです。

部屋の大きさと形を変える

部屋は、小部屋、中部屋、大部屋、特大部屋の四段階に分けています。

小部屋は多数配置しやすく、細かく枝分かれする階層を作ります。

大部屋や特大部屋には、将来的に2×2マスや3×3マスを使う大型の敵を配置する予定です。

部屋の形も長方形だけではありません。
「角が欠けた部屋」
「一部が段差のようにずれた部屋」
「中央に空白がある部屋」
「壁の一部がへこんだ部屋」
などを生成します。

同じ広さの部屋でも、障害物や壁の形が違えば、逃げる経路や攻撃できる位置などのプレイヤーの戦法も変わります。

接続口の数と位置をランダムにする

最初は、すべての部屋に上下左右一つずつ、決まった位置へ接続口を置いていました。

しかし、接続口が必ず壁の中央にあると、部屋の形が変わっても、通路の伸び方は似てしまいます。

そこで、接続口の数と位置もランダムにしました。
小部屋は接続口が少なく、大きな部屋ほど多くの接続口を持てます。
同じ形の部屋でも、
「左と下だけにつながる」
「上、右、下の三方向へつながる」
「一方向しか出口がない」
といった違いが生まれます。

接続口の位置も、壁の中央に固定していません。
同じ右側の壁でも、上寄りにつながる場合と、下寄りにつながる場合があります。

部屋の形だけでなく、
「どこから入り、どこから出るのか」
も変えることで、同じ部屋を使っても違う地形に見えるようにしています。

通路の幅を1マスから3マスにする

通路も、すべて同じ太さにはしない予定です。
現在は、1マス、2マス、3マスの中から幅を選びます。

最初はすべて1マス幅にしていました。
しかし、それでは大型の敵が移動できる場所が部屋の中だけに限られてしまいます。

そこで、広い通路も生成できるようにしました。

ただし、通路だけを後から太くすると、部屋側の入口と幅が合わなくなります。

そのため現在は、
「まず部屋に1マスから3マス幅の接続口を作る」
「その接続口と同じ幅の通路をつなげる」
という順番にしています。

これによって、一つの階層中に、細い通路と広い通路が混在します。

1マス幅の通路では、大型の敵は入りにくく、正面から一体ずつ敵へ対処しやすくなるかもしれません。
3マス幅の通路では移動しやすい一方で、複数の敵に囲まれる可能性があります。

部屋の中だけでなく、部屋と部屋の間でも、異なる状況を作りたいです。

まだできたのは地形だけ

現在できているのは、部屋と通路をつなぎ、地形を生成するところまでです。

敵やスクラップはまだ配置していません。

そのため、この地形が本当に面白い攻略を生み出すのかは、まだ分かりません。

次は、完成した地形へ敵とスクラップを配置していく予定です。

同じ形の部屋でも、
「小型の敵が複数いる」
「大型の敵が出口を塞いでいる」
「高価なスクラップの近くに危険な敵がいる」
「敵が少なく、安全に回収できる」
といった違いが生まれれば、プレイヤーが取る行動も変わります。

制作を始めてすぐの時は、コードの段階で、部屋に「戦闘部屋」「回収部屋」といった役割を先に与えるということをやっていました。
しかし、現在は生成された地形と敵とスクラップの組み合わせによって、その場所の役割が自然に生まれるゲームデザインにしたいと考えています。

まだ理想のダンジョンには遠いですが、少しずつ、自分が何度でも潜りたくなるランダム生成ダンジョンへ近づけていきます。

真ん中に大きな部屋。通路を通れない程大きい敵を配置したい。
中くらいの部屋がいくつか生成
細長い通路がある階層
特大部屋のある階層

いいなと思ったら応援しよう!