Example #1
0
    public void SpawnFinalDoor(Map map, RectIntExclusive area)
    {
        var spawnArea = new RectIntExclusive();

        spawnArea.xMin = 0;
        spawnArea.xMax = area.xMax;
        spawnArea.yMin = area.yMax - 1;
        spawnArea.yMax = area.yMax;
        var wallTiles = map.GetTilesOfType("Wall", spawnArea);

        for (int i = wallTiles.Count - 1; i >= 0; i--)
        {
            var tile         = wallTiles[i];
            var adjacentTile = Map.instance.tileObjects[tile.y - 1][tile.x];

            if (!adjacentTile.ContainsObjectOfType("Floor") || adjacentTile.ContainsObjectOfType("Wall"))
            {
                wallTiles.RemoveAt(i);
            }
        }
        int r = UnityEngine.Random.Range(0, wallTiles.Count);
        var tileToSpawnDoorOn = wallTiles[r];

        for (var node = tileToSpawnDoorOn.objectList.First; node != null;)
        {
            var next = node.Next;
            if (node.Value.objectName == "Wall")
            {
                tileToSpawnDoorOn.RemoveObject(node.Value, true);
            }
            node = next;
        }
        tileToSpawnDoorOn.SpawnAndAddObject(finalDoorPrefab);
    }
Example #2
0
    public static void DrawRect(Map map, RectIntExclusive area, Color color, Vector2 offset)
    {
        Vector2 lowerLeft  = new Vector2(area.xMin + offset.x, area.yMin + offset.y);
        Vector2 lowerRight = new Vector2(area.xMax + 1 - offset.x, area.yMin + offset.y);
        Vector2 upperLeft  = new Vector2(area.xMin + offset.x, area.yMax + 1 - offset.y);
        Vector2 upperRight = new Vector2(area.xMax + 1 - offset.x, area.yMax + 1 - offset.y);

        lowerLeft.x  *= map.tileWidth;
        lowerLeft.y  *= map.tileHeight;
        lowerRight.x *= map.tileWidth;
        lowerRight.y *= map.tileHeight;
        upperLeft.x  *= map.tileWidth;
        upperLeft.y  *= map.tileHeight;
        upperRight.x *= map.tileWidth;
        upperRight.y *= map.tileHeight;

        lowerLeft  += (Vector2)map.transform.position;
        lowerRight += (Vector2)map.transform.position;
        upperLeft  += (Vector2)map.transform.position;
        upperRight += (Vector2)map.transform.position;

        Debug.DrawLine(lowerLeft, lowerRight, color);
        Debug.DrawLine(lowerRight, upperRight, color);
        Debug.DrawLine(upperRight, upperLeft, color);
        Debug.DrawLine(upperLeft, lowerLeft, color);
    }
Example #3
0
 public void UpdateTiles(Map map, RectIntExclusive area)
 {
     for (int y = area.yMin; y <= area.yMax; y++)
     {
         for (int x = area.xMin; x <= area.xMax; x++)
         {
             AddTileObjects(map, x, y);
         }
     }
 }
Example #4
0
 public void ForEachTile(RectIntExclusive area, Action <Tile> action)
 {
     for (int y = area.yMax; y >= area.yMin; y--)
     {
         for (int x = area.xMax; x >= area.xMin; x--)
         {
             var tile = tileObjects[y][x];
             action(tile);
         }
     }
 }
Example #5
0
    // Add a floor tile that is part of a straight path between two rooms.
    // This works for vertical or horizontal paths by allowing the coordinates to be inverted
    // Returns true signify that the path should end if the tile is already a floor tile,
    // or if either neighbor perpendicular to the path is a floor tile
    bool AddStraightPathTile(int i, int j, RectIntExclusive area, bool invert)
    {
        bool isFloor = GetTile(i, j, invert) == TileType.FLOOR;
        bool isLesserNeighborFloor         = i - 1 > area.Min(!invert) && GetTile(i - 1, j, invert) == TileType.FLOOR;
        bool isGreaterNeighborFloor        = i + 1 < area.Max(!invert) && GetTile(i + 1, j, invert) == TileType.FLOOR;
        bool isLesserLesserNeighborFloor   = i - 1 - 1 > area.Min(!invert) && GetTile(i - 1 - 1, j, invert) == TileType.FLOOR;
        bool isGreaterGreaterNeighborFloor = i + 1 + 1 < area.Max(!invert) && GetTile(i + 1 + 1, j, invert) == TileType.FLOOR;

        SetTile(i, j, TileType.FLOOR, invert);

        return(isFloor || isLesserNeighborFloor || isGreaterNeighborFloor || isLesserLesserNeighborFloor || isGreaterGreaterNeighborFloor);
    }
Example #6
0
    void GenerateRooms(Map map, RectIntExclusive area, int numRooms)
    {
        for (int n = 0; n < numRooms; n++)
        {
            int w = Random.Range(3, map.width / 3);
            int h = Random.Range(3, map.height / 3);
            int x = Random.Range(0, map.width);
            int y = Random.Range(0, map.height - 2);

            GenerateRoom(map, x, y, w, h);
        }
    }
Example #7
0
    public void UpdateTiles(RectIntExclusive area)
    {
        var map = Map.instance;

        for (int y = area.yMin; y <= area.yMax; y++)
        {
            for (int x = area.xMin; x <= area.xMax; x++)
            {
                AddTileObjects(map, x, y);
            }
        }
    }
Example #8
0
    public List <Tile> GetTilesOfType(string type, RectIntExclusive area)
    {
        var tiles = new List <Tile>();

        ForEachTile(area, (tile) => {
            if (tile.ContainsObjectOfType(type))
            {
                tiles.Add(tile);
            }
        });

        return(tiles);
    }
Example #9
0
    // Create a straight (vertical or horizontal) path starting from the edge of an area, moving inwards until
    // either a floor tile is reached or a the path runs adjacent to a floor tile
    int CreateStraightPath(int i, int startOfPath, int endOfPath, RectIntExclusive area, bool invert)
    {
        int j    = startOfPath;
        int incr = endOfPath > startOfPath ? 1 : -1;

        for (; j != endOfPath; j += incr)
        {
            bool pathEnded = AddStraightPathTile(i, j, area, invert);
            if (pathEnded)
            {
                break;
            }
        }

        return(j);
    }
Example #10
0
    // Add a straight (vertical or horizontal) connecting path between two rooms
    // This works for vertical or horizontal paths by allowing the coordinates to be inverted
    // Each end of the path terminates when it reaches a floor tile or runs adjacent to a floor tile
    // A door is placed at each end of the path if appropriate
    private RectIntExclusive AddStraightConnectingPath(int i, RectIntExclusive areaA, RectIntExclusive areaB, bool invert)
    {
        int startOfPath = CreateStraightPath(i, areaA.Max(invert), areaA.Min(invert), areaA, invert);
        int endOfPath   = CreateStraightPath(i, areaB.Min(invert), areaB.Max(invert), areaB, invert);

        if (IsDoorSpot(i, startOfPath + 1, invert))
        {
            SetTile(i, startOfPath + 1, TileType.DOOR, invert);
        }
        if (IsDoorSpot(i - 1, startOfPath, invert))
        {
            SetTile(i - 1, startOfPath, TileType.DOOR, invert);
        }
        if (IsDoorSpot(i + 1, startOfPath, invert))
        {
            SetTile(i + 1, startOfPath, TileType.DOOR, invert);
        }
        if (IsDoorSpot(i, endOfPath - 1, invert))
        {
            SetTile(i, endOfPath - 1, TileType.DOOR, invert);
        }
        if (IsDoorSpot(i - 1, endOfPath, invert))
        {
            SetTile(i - 1, endOfPath, TileType.DOOR, invert);
        }
        if (IsDoorSpot(i + 1, endOfPath, invert))
        {
            SetTile(i + 1, endOfPath, TileType.DOOR, invert);
        }

        var pathArea = new RectIntExclusive();

        if (invert)
        {
            pathArea.SetMinMax(startOfPath - 1, endOfPath + 1, i - 1, i + 1);
        }
        else
        {
            pathArea.SetMinMax(i - 1, i + 1, startOfPath - 1, endOfPath + 1);
        }

        return(pathArea);
    }
Example #11
0
 public void ForEachTileThatAllowsSpawn(Action <Tile> doThis, RectIntExclusive area)
 {
     // If the area is larger than the total number of floor tiles it is more efficient to use the precomputed list
     if (area.width * area.height > tilesThatAllowSpawn.Count)
     {
         ForEachTileThatAllowsSpawn(doThis);
         return;
     }
     for (int y = area.yMax; y >= area.yMin; y--)
     {
         for (int x = area.xMax; x >= area.xMin; x--)
         {
             var tile = tileObjects[y][x];
             if (tile.AllowsSpawn())
             {
                 doThis(tile);
             }
         }
     }
 }
Example #12
0
    List <Vector2Int> GetLeftFloorTiles(RectIntExclusive area)
    {
        List <Vector2Int> floorTiles = new List <Vector2Int>();

        for (int y = area.yMin; y <= area.yMax; y++)
        {
            for (int x = area.xMin; x <= area.xMax; x++)
            {
                if (tiles[y][x] == TileType.FLOOR)
                {
                    floorTiles.Add(new Vector2Int(x, y));
                    break;
                }
                else if (tiles[y][x] == TileType.DOOR)
                {
                    break;
                }
            }
        }
        return(floorTiles);
    }
Example #13
0
    override public IEnumerator PreProcessMap(Map map, Biome biome)
    {
        tiles = new TileType[map.height][];
        for (int y = 0; y < map.height; y++)
        {
            tiles[y] = new TileType[map.width];
        }

        var itemsBiome     = new Biome();
        var itemsBiomeType = Instantiate(items);

        itemsBiome.biomeType = itemsBiomeType;
        itemsBiome.area      = biome.area;
        biome.subBiomes.Add(itemsBiome);

        yield return(new WaitForSeconds(animationDelay * 2));

        root      = new Node();
        root.area = biome.area;
        yield return(new WaitForSeconds(animationDelay));

        yield return(Map.instance.StartCoroutine(GenerateAreas(root, 1)));

        yield return(Map.instance.StartCoroutine(GenerateRooms(root, biome)));

        var mapArea = new RectIntExclusive(0, 0, Map.instance.width, Map.instance.height);

        AddWalls();

        if (animationDelay != 0)
        {
            UpdateTiles(mapArea);
            yield return(new WaitForSeconds(animationDelay));
        }
        PruneDoors();
        UpdateTiles(mapArea);

        //SpawnFinalDoor(map, area);
    }
Example #14
0
 virtual public void DrawDebug(RectIntExclusive area)
 {
     EditorUtil.DrawRect(Map.instance, area, Color.green);
 }
Example #15
0
    IEnumerator GenerateRooms(Node parent, Biome biome)
    {
        if (parent == null)
        {
            yield break;
        }

        if (parent.left == null && parent.right == null)
        {
            // Leaf node, actually generate a room
            int areaWidth  = parent.area.width - 2;
            int areaHeight = parent.area.height - 2;
            int minWidth   = Mathf.Max(1, areaWidth / 3);
            int minHeight  = Mathf.Max(1, areaHeight / 3);
            int w          = UnityEngine.Random.Range(minWidth, areaWidth);
            int h          = UnityEngine.Random.Range(minHeight, areaHeight);
            int xMin       = UnityEngine.Random.Range(parent.area.xMin + 1, parent.area.xMax - (w - 1));
            int yMin       = UnityEngine.Random.Range(parent.area.yMin + 1, parent.area.yMax - (h - 1));
            var rect       = new RectIntExclusive(xMin, yMin, w, h);
            parent.room = rect;

            for (int y = rect.yMin; y <= rect.yMax; y++)
            {
                for (int x = rect.xMin; x <= rect.xMax; x++)
                {
                    tiles[y][x] = TileType.FLOOR;
                }
            }

            var roomBiomeType = Instantiate(scorpions);
            var roomBiome     = new Biome();
            roomBiome.biomeType = roomBiomeType;
            roomBiome.area      = rect;
            biome.subBiomes.Add(roomBiome);

            for (int y = rect.yMin - 1; y <= rect.yMax + 1; y++)
            {
                for (int x = rect.xMin - 1; x <= rect.xMax + 1; x++)
                {
                    Map.instance.tileObjects[y][Map.instance.WrapX(x)].isAlwaysLit = true;
                    Map.instance.tileObjects[y][Map.instance.WrapX(x)].SetLit(true);
                }
            }
            if (animationDelay != 0)
            {
                UpdateTiles(parent.room);
                yield return(new WaitForSeconds(animationDelay));
            }
        }
        else
        {
            // Not a leaf node, keep traversing the tree
            yield return(Map.instance.StartCoroutine(GenerateRooms(parent.left, biome)));

            yield return(Map.instance.StartCoroutine(GenerateRooms(parent.right, biome)));

            // Ensure at least one path between the two subtrees
            if (parent.left.area.xMax == parent.right.area.xMax)
            {
                // Vertical split
                // Get a list of floor tiles at maximum y for each x in bottom split, and the min and max x values that have floor tiles
                List <Vector2Int> topTilesInBottomSplit = GetTopFloorTiles(parent.left.area);

                // Get a list of floor tiles at minimum y for each x in top split, and the min and max x values that have floor tiles
                List <Vector2Int> bottomTilesInTopSplit = GetBottomFloorTiles(parent.right.area);

                // Get the overlap between the two above lists
                bool             isConnected      = false;
                var              overlappingTiles = GetOverlap(topTilesInBottomSplit, bottomTilesInTopSplit, true, out isConnected);
                RectIntExclusive pathArea;

                if (!isConnected)
                {
                    if (overlappingTiles.Count != 0)
                    {
                        // Pick a random x position within the overlapping area to add a connecting path
                        int randomIndex = UnityEngine.Random.Range(0, overlappingTiles.Count);
                        int randomX     = overlappingTiles[randomIndex].tileA.x;
                        pathArea = AddStraightConnectingPath(randomX, parent.left.area, parent.right.area, false);
                        if (animationDelay != 0)
                        {
                            UpdateTiles(pathArea);
                        }
                    }
                    else
                    {
                        var bottomTileIndex = UnityEngine.Random.Range(0, topTilesInBottomSplit.Count);
                        var topTileIndex    = UnityEngine.Random.Range(0, bottomTilesInTopSplit.Count);
                        var bottomTile      = topTilesInBottomSplit[bottomTileIndex];
                        var topTile         = bottomTilesInTopSplit[topTileIndex];
                        AddAngledPath(bottomTile, topTile, true);
                        if (animationDelay != 0)
                        {
                            UpdateTiles(parent.area);
                        }
                    }
                    yield return(new WaitForSeconds(animationDelay));
                }
            }
            else
            {
                // Horizontal split
                // Get a list of floor tiles at maximum x for each y in left split, and the min and max y values that have floor tiles
                List <Vector2Int> rightTilesInLeftSplit = GetRightFloorTiles(parent.left.area);

                // Get a list of floor tiles at minimum x for each y in top split, and the min and max y values that have floor tiles
                List <Vector2Int> leftTilesInRightSplit = GetLeftFloorTiles(parent.right.area);

                // Get the overlap between the two above lists
                bool             isConnected      = false;
                var              overlappingTiles = GetOverlap(rightTilesInLeftSplit, leftTilesInRightSplit, false, out isConnected);
                RectIntExclusive pathArea;

                if (!isConnected)
                {
                    if (overlappingTiles.Count != 0)
                    {
                        // Pick a random y position within the overlapping area to add a connecting path
                        int randomIndex = UnityEngine.Random.Range(0, overlappingTiles.Count);
                        int randomY     = overlappingTiles[randomIndex].tileA.y;
                        pathArea = AddStraightConnectingPath(randomY, parent.left.area, parent.right.area, true);
                        if (animationDelay != 0)
                        {
                            UpdateTiles(pathArea);
                        }
                    }
                    else
                    {
                        var leftTileIndex  = UnityEngine.Random.Range(0, rightTilesInLeftSplit.Count);
                        var rightTileIndex = UnityEngine.Random.Range(0, leftTilesInRightSplit.Count);
                        var leftTile       = rightTilesInLeftSplit[leftTileIndex];
                        var rightTile      = leftTilesInRightSplit[rightTileIndex];
                        AddAngledPath(leftTile, rightTile, false);
                        if (animationDelay != 0)
                        {
                            UpdateTiles(parent.area);
                        }
                    }
                    yield return(new WaitForSeconds(animationDelay));
                }
            }
        }
    }
Example #16
0
 override public void DrawDebug(RectIntExclusive area)
 {
     base.DrawDebug(area);
     DrawArea(root);
 }
Example #17
0
 public static void DrawRect(Map map, RectIntExclusive area, Color color)
 {
     DrawRect(map, area, color, Vector2.zero);
 }
Example #18
0
    IEnumerator GenerateAreas(Node parent, float splitProbability)
    {
        if (UnityEngine.Random.value > splitProbability)
        {
            yield break;
        }

        bool horizontalHasRoom = parent.area.width > (minBSPArea * 2);
        bool verticalHasRoom   = parent.area.height > (minBSPArea * 2);

        if (!horizontalHasRoom && !verticalHasRoom)
        {
            yield break;
        }

        bool splitHorizontal;

        if (!verticalHasRoom)
        {
            splitHorizontal = true;
        }
        else if (!horizontalHasRoom)
        {
            splitHorizontal = false;
        }
        else
        {
            if (parent.area.width > parent.area.height)
            {
                splitHorizontal = true;
            }
            else if (parent.area.height > parent.area.width)
            {
                splitHorizontal = false;
            }
            else if (UnityEngine.Random.value > .5f)
            {
                splitHorizontal = false;
            }
            else
            {
                splitHorizontal = true;
            }
        }

        if (splitHorizontal)
        {
            int splitX = UnityEngine.Random.Range(parent.area.xMin + minBSPArea, parent.area.xMax - minBSPArea);
            RectIntExclusive newArea = new RectIntExclusive();
            newArea.xMin = parent.area.xMin;
            newArea.xMax = splitX;
            newArea.yMin = parent.area.yMin;
            newArea.yMax = parent.area.yMax;
            Node child1 = new Node();
            child1.area   = newArea;
            child1.parent = parent;
            parent.left   = child1;
            yield return(new WaitForSeconds(animationDelay));

            yield return(Map.instance.StartCoroutine(GenerateAreas(child1, splitProbability * .8f)));

            newArea      = new RectIntExclusive();
            newArea.xMin = splitX + 1;
            newArea.xMax = parent.area.xMax;
            newArea.yMin = parent.area.yMin;
            newArea.yMax = parent.area.yMax;
            Node child2 = new Node();
            child2.area   = newArea;
            child2.parent = parent;
            parent.right  = child2;
            yield return(new WaitForSeconds(animationDelay));

            yield return(Map.instance.StartCoroutine(GenerateAreas(child2, splitProbability * .8f)));
        }
        else
        {
            int splitY = UnityEngine.Random.Range(parent.area.yMin + minBSPArea, parent.area.yMax - minBSPArea);
            RectIntExclusive newArea = new RectIntExclusive();
            newArea.xMin = parent.area.xMin;
            newArea.xMax = parent.area.xMax;
            newArea.yMin = parent.area.yMin;
            newArea.yMax = splitY;
            Node child1 = new Node();
            child1.area   = newArea;
            child1.parent = parent;
            parent.left   = child1;
            yield return(new WaitForSeconds(animationDelay));

            yield return(Map.instance.StartCoroutine(GenerateAreas(child1, splitProbability * .8f)));

            newArea      = new RectIntExclusive();
            newArea.xMin = parent.area.xMin;
            newArea.xMax = parent.area.xMax;
            newArea.yMin = splitY + 1;
            newArea.yMax = parent.area.yMax;
            Node child2 = new Node();
            child2.area   = newArea;
            child2.parent = parent;
            parent.right  = child2;
            yield return(new WaitForSeconds(animationDelay));

            yield return(Map.instance.StartCoroutine(GenerateAreas(child2, splitProbability * .8f)));
        }
    }