見出し画像

【Unity】3Dローグライクゲームの作り方〜Step12-8〜

前回の記事はこちら
前回はダンジョンの自動生成を実装しました。

孫の区画に接続する

今のままだと自動生成されたダンジョンが一本道なので面白味がありません。なので孫の区画にも接続することで、変化を付けようと思います。
RandomDungeonクラスのCreateRoadsメソッドを変更します。

private void CreateRoads()
{
   for (int i = 0; i < areas.Count - 1; i++)
   {
       /*   省略   */
   }
   for (int i = 0; i < areas.Count - 2; i++)
   {
       if (Random.Range(0, 2) == 0) continue;
       if (areas[i].outLine.right < areas[i + 2].outLine.left)
           CreateHorizontalRoad(areas[i], areas[i + 2]);
       if (areas[i + 2].outLine.right < areas[i].outLine.left)
           CreateHorizontalRoad(areas[i + 2], areas[i]);
       if (areas[i].outLine.bottom < areas[i + 2].outLine.top)
           CreateVerticalRoad(areas[i], areas[i + 2]);
       if (areas[i + 2].outLine.bottom < areas[i].outLine.top)
           CreateVerticalRoad(areas[i + 2], areas[i]);
   }
}

二分の一の確率で孫の区画に接続させることにしました。
実行すると以下のようになります。

スクリーンショット 2020-06-02 4.44.57

スクリーンショット 2020-06-02 5.03.45

なおこの方法は簡易的なものなので、上図の中央辺りのように行き止まりを作ってしまうことがありますが、筆者的にはこの方がダンジョンらしい気がするのでこのままにしておきます。
気になる方は各自修正しておいて下さい。

階段を部屋に配置する

今のままだと階段を再配置していないので、階段が埋もれてしまったりしています。これをなんとかしましょう。
RandomDungeonクラスにメソッドを追加し、Createメソッドを変更して下さい。

// メソッドを追加
/**
* オブジェクトをフィールドに設置する
*/
private void SetObject(string name, string type, Field field, Array2D data)
{
   while (true) {
       int areaIdx = Random.Range(0, areas.Count);
       Rect2D room = areas[areaIdx].room;
       int x = Random.Range(room.left, room.right + 1);
       int y = Random.Range(room.top, room.bottom + 1);
       if (data.Get(x, y) != 0) continue;
       data.Set(x, y, 1);
       field.SetObject(name, type, x, y);
       break;
   }
}

/**
* オブジェクト群をフィールドに設置する
*/
private void SetObjects(Field field)
{
   Array2D tmpData = new Array2D(data.width, data.height);
   for (int x = 0; x < data.width; x++)
   {
       for (int y = 0; y < data.height; y++)
       {
           tmpData.Set(x, y, data.Get(x, y));
       }
   }
   SetObject("UpStairs", "Stairs", field, tmpData);
   SetObject("DownStairs", "Stairs", field, tmpData);
}

// メソッドを変更
public Array2D Create(int w, int h, Field field)
{
   /*   省略   */
   CreateRooms();
   SetObjects(field);
   CreateRoads();
   return data;
}

配置する部屋を決めて、その中にオブジェクトを配置するメソッドです。もし既にオブジェクトが配置されていれば、もう一度最初からやり直します。
これができたら、LoadFieldMapクラスのReadMapFileメソッドに少し付け足します。

if (group == null) return dungeon.Create(w, h, field);

テストしてみます。以下のように何度生成してもちゃんと部屋内に階段が設置されていればOKです。

スクリーンショット 2020-06-05 3.06.32

階段同士が重なっていないかも確認しておきましょう。

という訳で、短いですが今回はここまでにします。
次回は敵とアイテムの出現テーブルを作成する所から始めたいと思います。

この記事が気に入ったらサポートをしてみませんか?