自動生成のダンジョンを作る⑤
前回からの続きです。 ringogames.hatenablog.com
角の部分の処理
今のままでは、角部分に接合面が表れており、あまりにあまりなので、ここを修正していきます。
(接合部分がむき出し)
接合部分には、四角いピラーを立てていくことにしました。
ただ、全ての壁に対して必要になるということはなさそうです。 壁とピラーの関係を俯瞰で見ていくと 以下の2つの条件どちらかを満たしていれば、ピラーを立てる必要がなさそうです。
- AとCに同時に壁が存在する
- 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が作成されています。
むき出しの部分がなくなり、前回よりもまともになりました
ここまでのコードは以下にアップしています。