/// <summary> /// 最初の区画を作る /// </summary> /// <param name = "left" >左</param> /// <param name = "top" >上</param> /// <param name = "right" >右</param> /// <param name = "bottom">下</param> void Create_Division(int left, int top, int right, int bottom) { Dungeon_Division div = new Dungeon_Division(); div.Outer.Set_Position(left, top, right, bottom); division_list.Add(div); }
/// <summary> /// 部屋同士を通路でつなぐ /// </summary> void Connect_Rooms() { for (int i = 0; i < division_list.Count - 1; i++) { // リストの前後の区画は必ず接続できる Dungeon_Division a = division_list[i]; Dungeon_Division b = division_list[i + 1]; // 2つの部屋をつなぐ通路を作成 Create_Road(a, b); // 孫にも接続する for (int j = i + 2; j < division_list.Count; j++) { Dungeon_Division c = division_list[j]; if (Create_Road(a, c, true)) { // 孫に接続できたらおしまい break; } } } }
/// <summary> /// 指定した部屋の間を通路でつなぎ、部屋に隣接している通路を入口とする /// </summary> /// <param name="division_A">部屋1</param> /// <param name="division_B">部屋2</param> /// <param name="grand_child">孫チェックするかどうか</param> /// <returns>つなぐことができたらtrue</returns> bool Create_Road(Dungeon_Division division_A, Dungeon_Division division_B, bool grand_child = false) { // 上下でつながっている if (division_A.Outer.Bottom == division_B.Outer.Top || division_A.Outer.Top == division_B.Outer.Bottom) { // 部屋から伸ばす通路の開始位置を決める int x1 = Random.Range(division_A.Room.Left, division_A.Room.Right); int x2 = Random.Range(division_B.Room.Left, division_B.Room.Right); int y = 0; if (grand_child) { // すでに通路が存在していたらその情報を使用する if (division_A.Has_Road()) { x1 = division_A.Road.Left; } if (division_B.Has_Road()) { x2 = division_B.Road.Left; } } // A // | // B (Aが上側) if (division_A.Outer.Top > division_B.Outer.Top) { y = division_A.Outer.Top; // 通路を作成 division_B.Create_Road(x2, division_B.Room.Bottom + Define_Value.TILE_SCALE, x2 + Define_Value.TILE_SCALE, y); // 通路を作成 division_A.Create_Road(x1, y + Define_Value.TILE_SCALE, x1 + Define_Value.TILE_SCALE, division_A.Room.Top - Define_Value.TILE_SCALE); // 入口の座標を保持 entrance_position = new Vector2Int(x2, division_B.Room.Bottom); entrance_positions.Add(entrance_position); entrance_position = new Vector2Int(x1, division_A.Room.Top - Define_Value.ROOM_FLAME); entrance_positions.Add(entrance_position); } // B // | // A (Bが上側) else { y = division_B.Outer.Top; // 通路を作成 division_A.Create_Road(x1, division_A.Room.Bottom + Define_Value.TILE_SCALE, x1 + Define_Value.TILE_SCALE, y); // 通路を作成 division_B.Create_Road(x2, y, x2 + Define_Value.TILE_SCALE, division_B.Room.Top - Define_Value.TILE_SCALE); // 入口の座標を保持 entrance_position = new Vector2Int(x1, division_A.Room.Bottom); entrance_positions.Add(entrance_position); entrance_position = new Vector2Int(x2, division_B.Room.Top - Define_Value.ROOM_FLAME); entrance_positions.Add(entrance_position); } Fill_Dungeon_Rectangle_Road(division_A.Road); Fill_Dungeon_Rectangle_Road(division_B.Road); // 通路同士を接続する Fill_Horizontal_Line(x1, x2, y); // 通路を作れた return(true); } // 左右でつながっている if (division_A.Outer.Left == division_B.Outer.Right || division_A.Outer.Right == division_B.Outer.Left) { // 部屋から伸ばす通路の開始位置を決める int y1 = Random.Range(division_A.Room.Top, division_A.Room.Bottom); int y2 = Random.Range(division_B.Room.Top, division_B.Room.Bottom); int x = 0; if (grand_child) { // すでに通路が存在していたらその情報を使う if (division_A.Has_Road()) { y1 = division_A.Road.Top; } if (division_B.Has_Road()) { y2 = division_B.Road.Top; } } // B - A (Bが左側) if (division_A.Outer.Left > division_B.Outer.Left) { x = division_A.Outer.Left; // 通路を作成 division_B.Create_Road(division_B.Room.Right + Define_Value.TILE_SCALE, y2, x, y2 + Define_Value.TILE_SCALE); // 通路を作成 division_A.Create_Road(x + Define_Value.TILE_SCALE, y1, division_A.Room.Left - Define_Value.TILE_SCALE, y1 + Define_Value.TILE_SCALE); // 入口の座標を保持 entrance_position = new Vector2Int(division_B.Room.Right, y2); entrance_positions.Add(entrance_position); entrance_position = new Vector2Int(division_A.Room.Left - Define_Value.ROOM_FLAME, y1); entrance_positions.Add(entrance_position); } // A - B (Aが左側) else { x = division_B.Outer.Left; // 通路を作成 division_A.Create_Road(division_A.Room.Right + Define_Value.TILE_SCALE, y1, x, y1 + Define_Value.TILE_SCALE); // 通路を作成 division_B.Create_Road(x, y2, division_B.Room.Left - Define_Value.TILE_SCALE, y2 + Define_Value.TILE_SCALE); // 入口の座標を保持 entrance_position = new Vector2Int(division_A.Room.Right, y1); entrance_positions.Add(entrance_position); entrance_position = new Vector2Int(division_B.Room.Left - Define_Value.ROOM_FLAME, y2); entrance_positions.Add(entrance_position); } Fill_Dungeon_Rectangle_Road(division_A.Road); Fill_Dungeon_Rectangle_Road(division_B.Road); // 通路同士を接続する Fill_Virtical_Line(y1, y2, x); // 通路を作れた return(true); } // つなげなかった return(false); }
/// <summary> /// 区画を分割する /// </summary> /// <param name="is_vertical">垂直分割するかどうか</param> void Split_Divison(bool is_vertical) { // 末尾の要素を取り出し Dungeon_Division parent = division_list[division_list.Count - 1]; division_list.Remove(parent); // 子となる区画を生成 Dungeon_Division child = new Dungeon_Division(); if (is_vertical) { // 縦方向に分割する if (Check_Division_Size(parent.Outer.Height) == false) { // 縦の高さが足りない // 親区画を戻しておしまい division_list.Add(parent); return; } // 分割ポイントを求める int a = parent.Outer.Top + (Define_Value.MIN_ROOM + Define_Value.MERGIN_SIZE); int b = parent.Outer.Bottom - (Define_Value.MIN_ROOM + Define_Value.MERGIN_SIZE); // AB間の距離を求める int ab = b - a; // 最大の部屋サイズを超えないようにする ab = Mathf.Min(ab, Define_Value.MAX_ROOM); // 分割点を決める int p = a + Random.Range(0, ab + 1); // 子区画に情報を設定 child.Outer.Set_Position( parent.Outer.Left, p, parent.Outer.Right, parent.Outer.Bottom); // 親の下側をp地点まで縮める parent.Outer.Bottom = child.Outer.Top; } else { // 横方向に分割する if (Check_Division_Size(parent.Outer.Width) == false) { // 横幅が足りない // 親区画を戻しておしまい division_list.Add(parent); return; } // 分割ポイントを求める int a = parent.Outer.Left + (Define_Value.MIN_ROOM + Define_Value.MERGIN_SIZE); int b = parent.Outer.Right - (Define_Value.MIN_ROOM + Define_Value.MERGIN_SIZE); // AB間の距離を求める int ab = b - a; // 最大の部屋サイズを超えないようにする ab = Mathf.Min(ab, Define_Value.MAX_ROOM); // 分割点を求める int p = a + Random.Range(0, ab + 1); // 子区画に情報を設定 child.Outer.Set_Position( p, parent.Outer.Top, parent.Outer.Right, parent.Outer.Bottom); // 親の右側をp地点まで縮める parent.Outer.Right = child.Outer.Left; } // 次に分割する区画をランダムで決める if (Random.Range(0, 2) == 0) { // 子を分割する division_list.Add(parent); division_list.Add(child); } else { // 親を分割する division_list.Add(child); division_list.Add(parent); } // 分割処理を再帰呼び出し (分割方向は縦横交互にする) Split_Divison(!is_vertical); }
/// <summary> /// 指定した部屋の間を通路でつなぐ /// </summary> /// <param name="divA">部屋1</param> /// <param name="divB">部屋2</param> /// <param name="bGrandChild">孫チェックするかどうか</param> /// <returns>つなぐことができたらtrue</returns> bool Create_Road(Dungeon_Division divA, Dungeon_Division divB, bool bGrandChild = false) { if (divA.Outer.Bottom == divB.Outer.Top || divA.Outer.Top == divB.Outer.Bottom) { // 上下でつながっている // 部屋から伸ばす通路の開始位置を決める int x1 = Random.Range(divA.Room.Left, divA.Room.Right); int x2 = Random.Range(divB.Room.Left, divB.Room.Right); int y = 0; if (bGrandChild) { // すでに通路が存在していたらその情報を使用する if (divA.HasRoad()) { x1 = divA.Road.Left; } if (divB.HasRoad()) { x2 = divB.Road.Left; } } if (divA.Outer.Top > divB.Outer.Top) { // B - A (Bが上側) y = divA.Outer.Top; // 通路を作成 divA.CreateRoad(x1, y + 1, x1 + 1, divA.Room.Top); divB.CreateRoad(x2, divB.Room.Bottom, x2 + 1, y); } else { // A - B (Aが上側) y = divB.Outer.Top; // 通路を作成 divA.CreateRoad(x1, divA.Room.Bottom, x1 + 1, y); divB.CreateRoad(x2, y, x2 + 1, divB.Room.Top); } Fill_Dungeon_Rectangle(divA.Road); Fill_Dungeon_Rectangle(divB.Road); // 通路同士を接続する FillHLine(x1, x2, y); // 通路を作れた return(true); } if (divA.Outer.Left == divB.Outer.Right || divA.Outer.Right == divB.Outer.Left) { // 左右でつながっている // 部屋から伸ばす通路の開始位置を決める int y1 = Random.Range(divA.Room.Top, divA.Room.Bottom); int y2 = Random.Range(divB.Room.Top, divB.Room.Bottom); int x = 0; if (bGrandChild) { // すでに通路が存在していたらその情報を使う if (divA.HasRoad()) { y1 = divA.Road.Top; } if (divB.HasRoad()) { y2 = divB.Road.Top; } } if (divA.Outer.Left > divB.Outer.Left) { // B - A (Bが左側) x = divA.Outer.Left; // 通路を作成 divB.CreateRoad(divB.Room.Right, y2, x, y2 + 1); divA.CreateRoad(x + 1, y1, divA.Room.Left, y1 + 1); } else { // A - B (Aが左側) x = divB.Outer.Left; divA.CreateRoad(divA.Room.Right, y1, x, y1 + 1); divB.CreateRoad(x, y2, divB.Room.Left, y2 + 1); } Fill_Dungeon_Rectangle(divA.Road); Fill_Dungeon_Rectangle(divB.Road); // 通路同士を接続する FillVLine(y1, y2, x); // 通路を作れた return(true); } // つなげなかった return(false); }