Пример #1
0
        /// <summary>
        /// Gets the tile in the direction numberOfTilesAway from the currentTile.
        /// </summary>
        /// <param name="currentTile">The current tile we are at</param>
        /// <param name="direction">The direction we want to go in</param>
        /// <param name="numberOfTilesAway">How many spaces we want to move</param>
        /// <returns>The tile we ended at or NULL if no tile exists</returns>
        protected Tile GetTileToDirection(Tile currentTile, ETileDirection direction, int numberOfTilesAway = 1)
        {
            switch (direction)
            {
            case ETileDirection.NORTH:
                return(GetTile(currentTile.X, currentTile.Y + numberOfTilesAway));

            case ETileDirection.SOUTH:
                return(GetTile(currentTile.X, currentTile.Y - numberOfTilesAway));

            case ETileDirection.EAST:
                return(GetTile(currentTile.X + numberOfTilesAway, currentTile.Y));

            case ETileDirection.WEST:
                return(GetTile(currentTile.X - numberOfTilesAway, currentTile.Y));

            case ETileDirection.NORTH_EAST:
                return(GetTile(currentTile.X + numberOfTilesAway, currentTile.Y + numberOfTilesAway));

            case ETileDirection.NORTH_WEST:
                return(GetTile(currentTile.X - numberOfTilesAway, currentTile.Y + numberOfTilesAway));

            case ETileDirection.SOUTH_EAST:
                return(GetTile(currentTile.X + numberOfTilesAway, currentTile.Y - numberOfTilesAway));

            case ETileDirection.SOUTH_WEST:
                return(GetTile(currentTile.X - numberOfTilesAway, currentTile.Y - numberOfTilesAway));

            default:
                return(null);
            }
        }
Пример #2
0
        public static ETileDirection GetOppositeDirection(ETileDirection direction)
        {
            switch (direction)
            {
            case ETileDirection.EAST:
                return(ETileDirection.WEST);

            case ETileDirection.WEST:
                return(ETileDirection.EAST);

            case ETileDirection.NORTH:
                return(ETileDirection.SOUTH);

            case ETileDirection.SOUTH:
                return(ETileDirection.NORTH);

            case ETileDirection.NORTH_EAST:
                return(ETileDirection.NORTH_WEST);

            case ETileDirection.NORTH_WEST:
                return(ETileDirection.NORTH_EAST);

            case ETileDirection.SOUTH_EAST:
                return(ETileDirection.SOUTH_WEST);

            case ETileDirection.SOUTH_WEST:
                return(ETileDirection.SOUTH_EAST);

            default:
                return(ETileDirection.NONE);
            }
        }
Пример #3
0
        /// <summary>
        /// Deals with the actual visiting of tiles. It works by picking a random direction
        /// to carve in, and then we carve the cell we want to go to and the wall in between
        /// the two cells. When carving happens we add the carved cells to the region that
        /// our current cell belongs to. This function also deals with the KeepSameDirectionPercentage
        /// that determines how windy/jagged our maze is.
        /// </summary>
        /// <param name="currentTile">The current tile we are carving from</param>
        /// <param name="forceDirection">A forced direction to carve in. If not passed it will pick randomly</param>
        /// <returns>The tile we ended up carving into or NULL if no tile was picked</returns>
        private Tile CarveTile(Tile currentTile, ETileDirection forceDirection = ETileDirection.NONE)
        {
            ETileDirection chosenDirection;

            if (forceDirection == ETileDirection.NONE)
            {
                List <ETileDirection> directions = new List <ETileDirection>();

                foreach (ETileDirection direction in Tile.cardinal)
                {
                    if (CanCarve(currentTile, direction))
                    {
                        directions.Add(direction);
                    }
                }

                if (directions.Count() == 0)
                {
                    return(null);
                }

                if (directions.Contains(lastDirection) && UnityEngine.Random.Range(0, 100) < KeepSameDirectionPercentage)
                {
                    chosenDirection = lastDirection;
                }
                else
                {
                    chosenDirection = directions.ElementAt(UnityEngine.Random.Range(0, directions.Count()));
                }
            }
            else
            {
                chosenDirection = forceDirection;
            }

            lastDirection = chosenDirection;

            Tile nextTile = GetTileToDirection(currentTile, chosenDirection, 2);
            Tile wall     = GetTileToDirection(currentTile, chosenDirection, 1);

            nextTile.Type = ETileType.FLOOR;
            wall.Type     = ETileType.FLOOR;
            currentTile.ParentRegion.AddTile(wall);

            return(nextTile);
        }
Пример #4
0
        /// <summary>
        /// This function is the maze generation. We use a simple growing tree
        /// algorithm to build our maze. This works with a few steps:
        /// 1) Pick a starting cell and add it to our list
        /// 2) while we have cells to pick
        /// 3) pick a random cell
        /// 4) pick a random unvisted neighbor
        /// 5) add the neighbor to the list
        /// 6) if no neighbors exist remove the cell from the list
        ///
        /// We then repeat this until all our cells are either visited
        /// or surrounded by visted cells.
        /// </summary>
        private void GeneratePaths()
        {
            for (int y = 1; y < MapSize.y; y += 2)
            {
                for (int x = 1; x < MapSize.x; x += 2)
                {
                    Tile start = GetTile(x, y);
                    if (start.IsFloor() || IsBorderTile(start))
                    {
                        continue;
                    }

                    Stack <Tile> unvisited = new Stack <Tile>();
                    unvisited.Push(start);
                    Region currentRegion = new Region();

                    // take a cell out of the list
                    // carve a random cell next to it
                    // add that cell to the list

                    while (unvisited.Count > 0)
                    {
                        Tile currentTile = unvisited.Peek();
                        currentTile.Type = ETileType.FLOOR;
                        currentRegion.AddTile(currentTile);

                        Tile nextTile = CarveTile(currentTile);
                        if (nextTile == null)
                        {
                            unvisited.Pop();
                            lastDirection = ETileDirection.NONE;
                        }
                        else
                        {
                            unvisited.Push(nextTile);
                        }
                    }

                    Regions.Add(currentRegion);
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Determines if the currentTile is a border tile to any other tile.
        /// Border tile is defined as a border to a region, the map, or another visited tile.
        /// </summary>
        /// <param name="currentTile">The tile we want to check</param>
        /// <param name="skipDirection">Allows us to not look in a certain direction.
        ///     This is so that if we are carving we aren't checking the tile we just came from
        /// </param>
        /// <returns>Whether or not the tile is a border tile</returns>
        protected bool IsBorderTile(Tile currentTile, ETileDirection skipDirection = ETileDirection.NONE)
        {
            foreach (ETileDirection direction in Enum.GetValues(typeof(ETileDirection)))
            {
                if (direction != skipDirection && direction != ETileDirection.NONE)
                {
                    Tile tile = GetTileToDirection(currentTile, direction);
                    if (CheckIfTileIsOutOfMapOrInRegion(tile))
                    {
                        return(true);
                    }

                    if (!Tile.diagonals.Contains(direction) && tile.IsFloor())
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Пример #6
0
        /// <summary>
        /// Determines whether or not we can go from the currentTile
        /// and carve into the tile 2 spaces in the wanted direction.
        /// We use 2 spaces here because we need to carve through a
        /// wall and then carve through the cell we want to go to.
        /// </summary>
        /// <param name="currentTile">The tile we are at now</param>
        /// <param name="direction">The direction we want to carve in</param>
        /// <returns>Whether or not we can carve to the next tile</returns>
        private bool CanCarve(Tile currentTile, ETileDirection direction)
        {
            Tile tile = GetTileToDirection(currentTile, direction, 2);

            return(tile != null && !tile.IsFloor() && !IsBorderTile(tile, Tile.GetOppositeDirection(direction)));
        }