Example #1
0
    private GameObject SelectChunk(EdgeType exitType,
                                   Chunk.Direction exitDir,
                                   GameObject[] chunks, Vector3 position,
                                   out Chunk.EdgeDescription nextExit)
    {
        // Produce a list of all possible edges.
        var suitableEdges = new
                            Dictionary <GameObject, List <Chunk.EdgeDescription> >();

        foreach (GameObject chunk in chunks)
        {
            // Find details.
            Chunk details = chunk.GetComponent <Chunk>();
            var   edges   = new List <Chunk.EdgeDescription>();
            // Test edges using testChunk
            foreach (Chunk.EdgeDescription edge in details.Edges)
            {
                if (edge.type == exitType)
                {
                    int rotations   = edge.RotationsNeeded(exitDir);
                    var rotatedEdge = details.RotateEdge(edge, rotations);
                    if (TestChunk(details.Rotated(rotations),
                                  position - rotatedEdge.position - rotatedEdge.ExitVector))
                    {
                        edges.Add(edge);
                    }
                }
            }
            // If edges are found, add them to the dict.
            if (edges.Count != 0)
            {
                suitableEdges.Add(chunk, edges);
            }
        }
        if (suitableEdges.Count == 0)
        {
            nextExit = null;
            return(null);
        }

        // Select a chunk, and grab details.
        GameObject[] keys = new GameObject[suitableEdges.Keys.Count];
        suitableEdges.Keys.CopyTo(keys, 0);
        GameObject selectedChunk = keys[rng.Next(keys.Length)];

        // Select an edge.
        var possibleEdges = suitableEdges[selectedChunk];

        nextExit = possibleEdges[rng.Next(possibleEdges.Count)];

        return(selectedChunk);
    }
Example #2
0
    public bool generateTerrain()
    {
        // Initialise the dictionaries.
        initialise();

        // Place start
        GameObject[] startChunks = GetChunks(ChunkType.Entrance);
        PlaceChunk(startChunks[rng.Next(startChunks.Length)], 0);

        placedCells[Vector3.zero].distance = 0;

        // Place blocks directly outward until the exit is placed.
OuterWhile:
        while (openCells.Count != 0)
        {
            // Select next cell to fill.
            if (exitPosition == null)
            {
                openCells.Sort((Cell a, Cell b) => b.distance - a.distance);
            }
            else
            {
                openCells.Sort((Cell a, Cell b) => a.distance - b.distance);
            }
            Cell nextCell = openCells[0];
            position = nextCell.position;

            // Get exits and check to see if map is complete.
            List <Chunk.Direction> validExits = GetValidExits();

            // Try to place an exit.
            if (exitPosition == null)
            {
                ChunkType exit = ChunkType.Exit;
                if (nextCell.distance >= exitDifficulty)
                {
                    if (remainingChunks[0] != exit)
                    {
                        remainingChunks.Insert(0, exit);
                    }
                }
                else if (remainingChunks[0] == exit)
                {
                    remainingChunks.RemoveAt(0);
                }
            }

            // Prepare variables.
            Chunk.Direction       dir       = Chunk.Direction.FORWARD;
            Chunk.EdgeDescription edge      = null;
            GameObject            nextChunk = null;

            while (nextChunk == null)
            {
                // If no exits can be built on, rebase.
                if (validExits.Count == 0)
                {
                    deadEnds.Add(nextCell);
                    openCells.Remove(nextCell);
                    goto OuterWhile;
                }

                // Select a random exit.
                int selectedExit = rng.Next(validExits.Count);
                dir = validExits[selectedExit];
                var exit = placedCells[position].edges[(int)dir];

                // Select a chunk that fits there.
                var nextChunkType = remainingChunks.Count == 0 ?
                                    ChunkType.Edge : remainingChunks[0];

                GameObject[] chunks = GetChunks(nextChunkType);
                nextChunk = SelectChunk(exit, dir, chunks, position, out edge);
                if (nextChunk == null)
                {
                    validExits.RemoveAt(selectedExit);
                }
            }

            // Rotate it if needed, draw, and update x, y.
            Chunk details   = nextChunk.GetComponent <Chunk>();
            int   rotations = edge.RotationsNeeded(dir);
            edge    = details.RotateEdge(edge, rotations);
            details = details.Rotated(rotations);

            // Update position, place tile.
            position = position - edge.position - edge.ExitVector;
            PlaceChunk(nextChunk, rotations);

            // Empty the closed set.
            openCells.AddRange(deadEnds);
            deadEnds.Clear();

            if (details.type == ChunkType.Exit)
            {
                exitPosition = position;
            }
            if (remainingChunks.Count > 0)
            {
                remainingChunks.RemoveAt(0);
            }
        }

        // Actually generate the terrain.

        if (remainingChunks.Count == 0 && exitPosition != null)
        {
            foreach (Cell cell in deadEnds)
            {
                // Place dead ends.
                GameObject[] blocks = GetChunks(ChunkType.Block);
                for (int dir = 0; dir < 4; dir++)
                {
                    if (cell.edges[dir] != CLOSED)
                    {
                        position = cell.position + DirVector(dir);
                        PlaceChunk(blocks[rng.Next(blocks.Length)], 0);
                    }
                }
            }

            // Now instantiate the terrain, and create the grid.
            terrain      = new GameObject();
            terrain.name = "Chunks"; // To make the editor neater.
            foreach (InstantiateCall obj in instantiateCalls)
            {
                obj.Instantiate(terrain);
            }
            CreateGrid();

            return(true);
        }
        else
        {
            return(false);
        }
    }