自動生成のダンジョンを作る⑤

前回からの続きです。 ringogames.hatenablog.com

角の部分の処理

今のままでは、角部分に接合面が表れており、あまりにあまりなので、ここを修正していきます。

(接合部分がむき出し)

接合部分には、四角いピラーを立てていくことにしました。

ただ、全ての壁に対して必要になるということはなさそうです。 壁とピラーの関係を俯瞰で見ていくと 以下の2つの条件どちらかを満たしていれば、ピラーを立てる必要がなさそうです。

  1. AとCに同時に壁が存在する
  2. BとDに同時に壁が存在する

そのため、これ以外の場合にのみピラーを設置することとします。

まず、Pillarに隣接する4つの壁を保存しておくためのクラスを作成しました。 上記の仕組みが分かりやすいように変数名もA,B,C,Dに・・・。

namespace RG
{

    [System.Serializable]
    public class DungeonPillarPoint
    {
        public DungeonPillarPoint(Vector3 pos)
        {
            Pos = pos;
        }

        public Vector3 Pos = Vector3.zero;
        public DungeonEdge EdgeA = null;
        public DungeonEdge EdgeB = null;
        public DungeonEdge EdgeC = null;
        public DungeonEdge EdgeD = null;
    }
}

Pillarの2次元Indexで辞書を作成したかったため、2次元インデックスがキーとできるようにクラスを作成

        private class DungeonPillarIndex
        {
            public int RowNo = -1;
            public int ColumnNo = -1;
            public DungeonPillarIndex(int rowNo, int columnNo)
            {
                RowNo = rowNo;
                ColumnNo = columnNo;
            }

            public override int GetHashCode()
            {
                return this.RowNo.GetHashCode() + this.ColumnNo.GetHashCode();
            }


            public override bool Equals(object other)
            {
                DungeonPillarIndex otherPillarIndex = other as DungeonPillarIndex;
                if (otherPillarIndex == null)
                {
                    return false;
                }
                else
                {
                    if(RowNo == otherPillarIndex.RowNo && ColumnNo == otherPillarIndex.ColumnNo)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
            }
        }

エッジ作成時にそれぞれのピラーに対して隣接するエッジの情報を保存 この部分と

                    //pillar point lower
                    var pillarIndexLower = new DungeonPillarIndex(i, j);
                    if (m_dictDungeonPillarPoint.ContainsKey(pillarIndexLower))
                    {
                        var pillarPoint = m_dictDungeonPillarPoint[pillarIndexLower];
                        pillarPoint.EdgeB = edge;
                    }

                    //pillar point upper
                    var pillarIndexUpper = new DungeonPillarIndex(i + 1, j);
                    if (m_dictDungeonPillarPoint.ContainsKey(pillarIndexUpper))
                    {
                        var pillarPoint = m_dictDungeonPillarPoint[pillarIndexUpper];
                        pillarPoint.EdgeD = edge;
                    }

この部分

                    //pillar point left
                    var pillarIndexLeft = new DungeonPillarIndex(i, j);
                    if (m_dictDungeonPillarPoint.ContainsKey(pillarIndexLeft))
                    {
                        var pillarPoint = m_dictDungeonPillarPoint[pillarIndexLeft];
                        pillarPoint.EdgeC = edge;
                    }

                    //pillar point right
                    var pillarIndexRight = new DungeonPillarIndex(i, j + 1);
                    if (m_dictDungeonPillarPoint.ContainsKey(pillarIndexRight))
                    {
                        var pillarPoint = m_dictDungeonPillarPoint[pillarIndexRight];
                        pillarPoint.EdgeA = edge;
                    }

最後に上記のルールに従い、Pillarを作成

            //instantiate pillars
            foreach (DungeonPillarPoint point in m_dictDungeonPillarPoint.Values)
            {
                if(
                    (m_edges.Contains(point.EdgeA) && m_edges.Contains(point.EdgeC)) ||
                    (m_edges.Contains(point.EdgeB) && m_edges.Contains(point.EdgeD))
                    )
                {
                    //do nothing
                }
                else
                {
                    //make pillar
                    if (m_pillarObject)
                    {
                        Instantiate(m_pillarObject, point.Pos, Quaternion.identity, rootObject.transform);
                    }
                }
            }

実行すると、必要な部分にのみPillarが作成されています。

むき出しの部分がなくなり、前回よりもまともになりました

ここまでのコードは以下にアップしています。

gitlab.com