Exemple #1
0
    IEnumerator FloodFill(IntGrid floodFilledCells, ObjectPool filledTiles, Point point)
    {
        Point up    = point + Vector2.up;
        Point down  = point + Vector2.down;
        Point left  = point + Vector2.left;
        Point right = point + Vector2.right;

        if (point.x < 0 || point.y < 0 || point.x > dungeonWidth - 1 || point.y > dungeonHeight - 1)
        {
            floodFilledPointCount--;
            yield break;
        }
        if (floodFilledCells[point.x, point.y] != 0)
        {
            floodFilledPointCount--;
            yield break;
        }

        floodFilledCells[point.x, point.y] = 2;

        ObjectPool.PooledObject pooledObj = filledTiles.GetObjectFromPool;
        pooledObj.position = new Vector2(
            point.x - (dungeonWidth / 2) + (pooledObj.scale.x / 2),
            point.y - (dungeonHeight / 2) + (pooledObj.scale.y / 2)
            );

        SpriteRenderer r = pooledObj.gameObject.GetComponent <SpriteRenderer>();

        if (r != null)
        {
            r.color = Color.red;
        }

        yield return(null);

        if (dungeon[up] == 0)
        {
            floodFilledPointCount++;
            StartCoroutine(FloodFill(floodFilledCells, filledTiles, up));
        }
        if (dungeon[down] == 0)
        {
            floodFilledPointCount++;
            StartCoroutine(FloodFill(floodFilledCells, filledTiles, down));
        }
        if (dungeon[left] == 0)
        {
            floodFilledPointCount++;
            StartCoroutine(FloodFill(floodFilledCells, filledTiles, left));
        }
        if (dungeon[right] == 0)
        {
            floodFilledPointCount++;
            StartCoroutine(FloodFill(floodFilledCells, filledTiles, right));
        }

        floodFilledPointCount--;
    }
Exemple #2
0
    public Maze(int width, int height, float complexity = 0.75f, float density = 0.75f)
    {
        this.width      = width;
        this.height     = height;
        this.shape      = new int[] { height, width };
        this.complexity = (int)(complexity * (5.0f * (this.shape[0] + this.shape[1])));
        this.density    = (int)(density * ((this.shape[0] / 2) * (this.shape[1] / 2)));

        this._mazeGrid = new IntGrid(this.shape[1], this.shape[0]);
        GenerateMaze();
    }
Exemple #3
0
    public Maze(IntGrid maze, bool shouldGenerate = false, float complexity = 0.75f, float density = 0.75f)
    {
        int width  = maze.GetLength(0);
        int height = maze.GetLength(1);

        this.width  = width;
        this.height = height;

        this.shape      = new int[] { height, width };
        this.complexity = (int)(complexity * (5.0f * (this.shape[0] + this.shape[1])));
        this.density    = (int)(density * ((this.shape[0] / 2) * (this.shape[1] / 2)));

        this._mazeGrid = maze;
        if (shouldGenerate)
        {
            GenerateMaze();
        }
    }
Exemple #4
0
    // TODO: Refactor this to use a different maze gen algorithm, this one kinda blows
    public void GenerateMaze(IntGrid _maze = null)
    {
        IntGrid mazeArray = this._mazeGrid;

        // Generate inner maze
        for (int i = 0; i < this.density; i++)
        {
            int x = Random.Range(0, this.shape[1] / 2) * 2;
            int y = Random.Range(0, this.shape[0] / 2) * 2;
            if (mazeArray[x, y] == 0)
            {
                mazeArray[x, y] = 1;

                for (int j = 0; j < this.complexity; j++)
                {
                    List <Vector3> neighbours = new List <Vector3>();
                    if (x > 1)
                    {
                        neighbours.Add(new Vector3(x - 2, y));
                    }
                    if (x < this.shape[1] - 2)
                    {
                        neighbours.Add(new Vector3(x + 2, y));
                    }
                    if (y > 1)
                    {
                        neighbours.Add(new Vector3(x, y - 2));
                    }
                    if (y < this.shape[0] - 2)
                    {
                        neighbours.Add(new Vector3(x, y + 2));
                    }
                    if (neighbours.Count > 0)
                    {
                        int     randIndex = Random.Range(0, neighbours.Count);
                        Vector3 neighbour = neighbours[randIndex];
                        int     x_        = (int)neighbour.x;
                        int     y_        = (int)neighbour.y;
                        if (mazeArray[x_, y_] == 0)
                        {
                            mazeArray[x_, y_] = 1;
                            mazeArray[x_ + (x - x_) / 2, y_ + (y - y_) / 2] = 1;
                            x = x_;
                            y = y_;
                        }
                    }
                }
            }
        }

        // Border the maze
        int mazeWidth  = mazeArray.GetLength(0);
        int mazeHeight = mazeArray.GetLength(1);

        for (int i = 0; i < mazeArray.GetLength(0); i++)
        {
            for (int j = 0; j < mazeArray.GetLength(1); j++)
            {
                if (i == 0 || j == 0 || i == mazeWidth - 1 || j == mazeHeight - 1)
                {
                    mazeArray[j, i] = 1;
                }
            }
        }

        this._mazeGrid = mazeArray;
    }
Exemple #5
0
    IEnumerator GenerateDungeon()
    {
        if (dungeonHeight % 2 == 0)
        {
            throw new System.FormatException("dungeonHeight should be an odd number");
        }
        if (dungeonWidth % 2 == 0)
        {
            throw new System.FormatException("roomMaxDimension should be an odd number");
        }
        if (roomMinDimension % 2 == 0)
        {
            throw new System.FormatException("roomMinDimension should be an odd number");
        }
        if (roomMaxDimension % 2 == 0)
        {
            throw new System.FormatException("roomMaxDimension should be an odd number");
        }
        if (tileSize % 2 == 0)
        {
            throw new System.FormatException("tileSize should be an odd number");
        }

        isGenerating       = true;
        retryCount         = 0;
        dungeonRect        = Rect.zero;
        dungeonRect.height = dungeonHeight - 2; // minus 2 to give a 1 unit edge padding around the whole dungeon
        dungeonRect.width  = dungeonWidth - 2;  // minus 2 to give a 1 unit edge padding around the whole dungeon
        dungeonRect.center = transform.position;
        if (tiles != null)
        {
            tiles.ClearPool();
        }

        Camera.main.orthographicSize = Mathf.Max(dungeonWidth / 2, dungeonHeight / 2) + 2;
        dungeon = new IntGrid(dungeonWidth, dungeonHeight);
        tiles   = new ObjectPool(roomPrefab, dungeonWidth * dungeonHeight, false, false, transform);

        // make retryAttempts attempts to place rooms randomly within the dungeon
        while (retryCount < retryAttempts)
        {
            Vector2 randomPosition = new Vector2(ClampValueToOddNumber(Random.Range(0, dungeonWidth) - dungeonWidth / 2f), ClampValueToOddNumber(Random.Range(0, dungeonHeight) - dungeonHeight / 2f));
            Vector2 randomScale    = new Vector2(ClampValueToOddNumber(Random.Range(roomMinDimension, roomMaxDimension)), ClampValueToOddNumber(Random.Range(roomMinDimension, roomMaxDimension)));

            Collider2D overlapBox = Physics2D.OverlapBox(randomPosition, randomScale + (Vector2.one * minDistanceBetweenRooms * 2), 0f);
            if (overlapBox == null && IsRoomInBounds(randomPosition, randomScale))
            {
                ObjectPool.PooledObject room = tiles.GetObjectFromPool;
                room.SetActive(true);
                room.position = randomPosition;
                room.scale    = randomScale;
                yield return(new WaitForSeconds(0.1f));
            }
            else
            {
                retryCount++;
            }
        }

        // carve out the rooms from the array of cells and disable the rooms in the pool
        foreach (KeyValuePair <string, ObjectPool.PooledObject> entry in tiles.GetObjectPool)
        {
            if (entry.Value.activeInHierarchy)
            {
                Vector3    roomPositionOffset = new Vector3(dungeonWidth / 2f, dungeonHeight / 2f);
                GameObject room  = entry.Value.gameObject;
                Vector3    scale = room.transform.localScale;
                for (float x = -scale.x / 2; x <= scale.x / 2; x++)
                {
                    for (float y = -scale.y / 2; y <= scale.y / 2; y++)
                    {
                        Point point = new Point((int)x, (int)y) + room.transform.position + roomPositionOffset;
                        dungeon[point.x, point.y] = 2;
                    }
                }

                tiles.Disable(entry.Key);
                yield return(null);
            }
        }

        // generate the maze in the empty space of the dungeon
        dungeon = new Maze(dungeon, true).mazeGrid;

        yield return(StartCoroutine(RenderDungeon()));

        yield return(StartCoroutine(StartFloodFill()));

        yield return(StartCoroutine(RenderDungeon()));

        yield return(StartCoroutine(RemoveDeadEnds()));

        yield return(StartCoroutine(RenderDungeon()));

        isGenerating = false;
    }
Exemple #6
0
    IEnumerator StartFloodFill()
    {
        floodFilledPointCount = 0;
        IntGrid    floodFilledCells = new IntGrid(dungeonWidth, dungeonHeight);
        ObjectPool filledTiles      = new ObjectPool(roomPrefab, 0, true, true, new GameObject("Filled Tiles").transform);

        for (int i = 0; i < dungeonWidth; i++)
        {
            for (int j = 0; j < dungeonHeight; j++)
            {
                floodFilledCells[i, j] = dungeon[i, j];
            }
        }

        int x = Random.Range(0, dungeonWidth - 1);
        int y = Random.Range(0, dungeonHeight - 1);

        while (floodFilledCells[x, y] == 1)
        {
            x = Random.Range(0, dungeonWidth);
            y = Random.Range(0, dungeonHeight);
        }

        floodFilledPointCount++;;
        StartCoroutine(FloodFill(floodFilledCells, filledTiles, new Point(x, y)));

        while (floodFilledPointCount > 0)
        {
            yield return(null);
        }

        int filledCount = 0;

        for (int i = 0; i < dungeonWidth; i++)
        {
            for (int j = 0; j < dungeonHeight; j++)
            {
                if (floodFilledCells[i, j] == 2)
                {
                    filledCount++;
                }
            }
        }

        if (filledCount < (dungeonHeight * dungeonWidth * 0.045f))   // filled count < 10% of 45% of tile count
        {
            if (fillAttempts >= 0)
            {
                filledTiles.ClearPool();
                Debug.Log("Fill quality below threshold, restarting fill");
                fillAttempts--;
                StartCoroutine(StartFloodFill());
            }
            else
            {
                Debug.Log("Refill attemps reached, restarting dungeon generation");
                StartCoroutine(GenerateDungeon());
            }
        }
        else
        {
            for (int i = 0; i < dungeonWidth; i++)
            {
                for (int j = 0; j < dungeonHeight; j++)
                {
                    if (floodFilledCells[i, j] == 0)
                    {
                        floodFilledCells[i, j] = 1;
                    }
                }
            }
        }

        filledTiles.ClearPool();
        dungeon = floodFilledCells;
    }