private void SetStart(Graph2D graph, int start, HashSet <int> walkables) { int startPointPlaceX = ( int )this.startPointPlace.x; int startPointPlaceY = ( int )this.startPointPlace.y; int[] coord = graph.IndexToCoord(start); if (coord[0] + startPointPlaceX > this.col - 1) { coord[0] = this.col - 1 - startPointPlaceX; } if (coord[1] + startPointPlaceY > this.row - 1) { coord[1] = this.row - 1 - startPointPlaceY; } for (int i = 0; i < startPointPlaceX; i++) { int x = coord[0] + i; for (int j = 0; j < startPointPlaceY; j++) { int y = coord[1] + j; this.SetTileWalkable(graph.CoordToIndex(x, y), walkables); } } //计算起始范围的中点坐标(世界坐标) float i0 = (coord[0] + startPointPlaceX - coord[0]) * 0.5f + coord[0]; float i1 = -(coord[1] + startPointPlaceY - coord[1]) * 0.5f - coord[1]; this.centerOfStartRange = this._localToWorld.TransformPoint(new FVec3(i0, 0, i1)); }
public Maze(FPseudoRandom random, FVec3 scale, FVec3 offset, int row, int col, int startIndex, int endIndex, FVec2 startPointPlace) { this.startPointPlace = startPointPlace; if (this.row < ( int )this.startPointPlace.y + 3 || this.col < ( int )this.startPointPlace.x + 3) { throw new Exception("The row or col invaild"); } this.scale = scale; this.offset = offset; this.row = row; this.col = col; this._localToWorld = FMat4.FromTRS(this.offset, FQuat.identity, this.scale); this._worldToLocal = FMat4.NonhomogeneousInverse(this._localToWorld); //创建二维图 Graph2D graph2 = this.CreateFullDigraph(random); //创建格子 this.CreateTiles(graph2); //是否随机起点和终点 this.startIndex = startIndex < 0 ? this.RandomIndexWithinBorder(random) : startIndex; if (endIndex < 0) { int[] candidate = new int[5]; for (int i = 0; i < 5; i++) { candidate[i] = this.RandomIndexWithinBorder(random); } endIndex = this.GetFarthestToStartIndex(this.startIndex, candidate); } this.endIndex = endIndex; //初始化起点范围 HashSet <int> walkablesHs = new HashSet <int>(); this.SetStart(graph2, this.startIndex, walkablesHs); //创建起点和终点 int[] coord = graph2.IndexToCoord(this.startIndex); Delaunay.DVertex startVertex = new Delaunay.DVertex(coord[0], coord[1]); coord = graph2.IndexToCoord(this.endIndex); Delaunay.DVertex endVertex = new Delaunay.DVertex(coord[0], coord[1]); //创建外圆周附近的顶点 List <Delaunay.DVertex> vertices1 = this.GenVertices(24, 1f, 0.8f, 24, random); //创建内圆周附近的顶点 List <Delaunay.DVertex> vertices2 = this.GenVertices(12, 0.2f, 0.6f, 12, random); //合并所有顶点 List <Delaunay.DVertex> vertices = new List <Delaunay.DVertex> { startVertex, endVertex }; vertices.AddRange(vertices1); vertices.AddRange(vertices2); //点集合的三角化 List <Delaunay.DTriangle> triangles = Delaunay.Triangulate(vertices); //从三角形集合创建图 GraphBase graph = Tools.TrianglesToGraph(triangles, random.NextFloat); //Prim算法创建最小生成树 List <GraphEdge> edges = GraphSearcher.PrimSearch(graph, triangles[0].v0); //每条边用A*算法生成路径 int count = edges.Count; for (int i = 0; i < count; i++) { GraphEdge edge = edges[i]; Delaunay.DVertex v0 = vertices[edge.from]; Delaunay.DVertex v1 = vertices[edge.to]; int[] path = GraphSearcher.AStarSearch(graph2, graph2.CoordToIndex(( int )v0.x, ( int )v0.y), graph2.CoordToIndex(( int )v1.x, ( int )v1.y)); this.SetPathWalkable(path, walkablesHs); //把顶点扩展成房间 if (i == 0) { this.SetIndexToWalkable(graph2, ( int )v0.x, ( int )v0.y, random.Next(1, 3), random.Next(1, 3), walkablesHs); } this.SetIndexToWalkable(graph2, ( int )v1.x, ( int )v1.y, random.Next(1, 3), random.Next(1, 3), walkablesHs); } this.walkables = walkablesHs.ToArray(); }