public static ConnectionInfo FindConnection(TileRegion regionA, TileRegion regionB)
        {
            Assert.IsNotNull(regionA);
            Assert.IsNotNull(regionB);
            Assert.AreNotEqual(regionA, regionB);

            var bestConnection = new TempConnection(Coord.zero, Coord.zero, float.MaxValue);
            int indexA         = 0;

            while (indexA < regionA.Count)
            {
                int indexB       = 0;
                var bestThisLoop = new TempConnection(regionA[indexA], Coord.zero, float.MaxValue);
                while (indexB < regionB.Count)
                {
                    Coord tileB    = regionB[indexB];
                    float distance = bestThisLoop.tileA.Distance(tileB);
                    if (distance < bestThisLoop.distance)
                    {
                        bestThisLoop = new TempConnection(bestThisLoop.tileA, tileB, distance);
                    }
                    indexB += (int)distance; // distance is never < 1, as minimum occurs with diagonally adjacent tiles
                }
                if (bestThisLoop.distance < bestConnection.distance)
                {
                    bestConnection = bestThisLoop;
                }
                indexA += (int)bestThisLoop.distance;
            }
            return(new ConnectionInfo(bestConnection.tileA, bestConnection.tileB, regionA.Index, regionB.Index, bestConnection.distance));
        }
Пример #2
0
        /* The following method has some subtleties to it that need to be explained. The purpose of it is to trace out the
         * floor tiles in the room that are adjacent to a wall tile. The tricky part is ensuring that this is done
         * in an orderly fashion, i.e. that it traces out a more or less continuous path (some error is fine, but a random
         * ordering is not, as the ordering of the edge tiles is needed for an enormous optimization in the connectivity
         * algorithm used elsewhere).
         *
         * The basic idea is to start on an edge tile, and then perform a depth-first search along edge tiles. The difficulty
         * comes from two situations. First, consider this example:
         *
         * x x o
         * x x o
         * 1 2 o
         * o o o
         *
         * x represents wall, o represents floor, numbers represent the path travelled (and the order). If we only
         * look at horizontal neighbors, the search will terminate at 2, because no adjacent floor is adjacent to a wall.
         * So we need to look at diagonal neighbors. That leads to the following problem:
         *
         * x x x x
         * x x o x
         * x 3 x x
         * 1 2 x x
         *
         * The remaining o is not connected to the path so far, but it's diagonally adjacent to the 3. This is handled
         * by explicitly checking for this situation: in order to take a diagonal jump, one of the
         * two adjacent tiles must be a floor. i.e. one of these situations:
         *
         * x x x x     x x x x      x x x x
         * x x o x     x o o x      x o o x
         * x 3 o x     x 3 x x      x 3 o x
         * 1 2 x x     1 2 x x      1 2 x x
         *
         * The final complexity is the possibility of the path jumping, leading to irregularities in the edges.
         * Example:
         *
         * x x o o o 8 x
         * x x 4 5 6 7 x
         * 1 2 3 x x o x
         * o o o x x o x
         *
         * Ultimately this level of error is accepted as is. */

        /// <summary>
        /// Extract the edge tiles from this region.
        /// </summary>
        /// <param name="region">Must not be empty.</param>
        public TileRegion Extract(TileRegion region)
        {
            Assert.AreNotEqual(region.Count, 0, "Room is empty!");
            var   boundary  = new Boundary(map.Length, map.Width);
            var   edgeTiles = new List <Coord>(region.Count);
            var   stack     = new Stack <Coord>();
            Coord firstTile = GetStartingEdgeTile(map, region);

            stack.Push(firstTile);
            edgeTiles.Add(firstTile);
            visited[firstTile.x, firstTile.y] = true;

            while (stack.Count > 0)
            {
                Coord tile = stack.Pop();
                foreach (Coord adj in GetAdjacentCoords(tile, pooledAdjacentTiles))
                {
                    if (boundary.IsInBounds(adj) && !visited[adj.x, adj.y] && FoundEdgeTile(tile, adj, map))
                    {
                        visited[adj.x, adj.y] = true;
                        stack.Push(adj);
                        edgeTiles.Add(adj);
                    }
                }
            }
            return(new TileRegion(edgeTiles, region.Index));
        }
Пример #3
0
        static TileRegion[] ExtractEdges(Map map, List <TileRegion> regions)
        {
            var extractor = new EdgeExtractor(map);
            var rooms     = new TileRegion[regions.Count];

            for (int i = 0; i < rooms.Length; i++)
            {
                rooms[i] = extractor.Extract(regions[i]);
            }
            return(rooms);
        }
Пример #4
0
 static Coord GetStartingEdgeTile(Map map, TileRegion region)
 {
     // Note that in practice, this should return the very first item in alltiles.
     return(region.First(tile => map.IsAdjacentToWall(tile.x, tile.y)));
 }