/** * build a list of walls in the maze, cells in the maze, and how they connect to each other. * @param out * @throws IOException */ public void GenerateMaze() { // build the cells Maze.Cells = new Maze.Cell[Maze.MazeSize.x, Maze.MazeSize.y]; for (int y = 0; y < Maze.MazeSize.y; ++y) { for (int x = 0; x < Maze.MazeSize.x; ++x) { Maze.Cells[x, y] = new Maze.Cell(x, y, Maze.Wall.All); } } int unvisitedCells = Maze.Cells.Length; // -1 for initial cell. int cellsOnStack = 0; // Make the initial cell the current cell and mark it as visited Maze.Coord currentCell = new Maze.Coord(0, 0); Maze.Cells[0, 0].visited = true; --unvisitedCells; // While there are unvisited cells while (unvisitedCells > 0) { // If the current cell has any neighbours which have not been visited // Choose randomly one of the unvisited neighbours Maze.Coord nextCell = chooseUnvisitedNeighbor(currentCell); if (nextCell != null) { int cx = currentCell.x; int cy = currentCell.y; int nx = nextCell.x; int ny = nextCell.y; // Push the current cell to the stack Maze.Cells[cx, cy].onStack = true; ++cellsOnStack; // Remove the wall between the current cell and the chosen cell Maze.Wall wall = Maze.GetWallBetween(currentCell, nextCell); if (wall != Maze.Wall.None) { Maze.Cells[cx, cy].RemoveWall(wall); Maze.Cells[nx, ny].RemoveWall(Maze.GetOppositeWall(wall)); } // Make the chosen cell the current cell and mark it as visited currentCell = nextCell; cx = currentCell.x; cy = currentCell.y; Maze.Cells[cx, cy].visited = true; --unvisitedCells; } else if (cellsOnStack > 0) { // else if stack is not empty pop a cell from the stack for (int y = 0; y < Maze.MazeSize.y; ++y) { for (int x = 0; x < Maze.MazeSize.x; ++x) { if (Maze.Cells[x, y].onStack) { // Make it the current cell currentCell = new Maze.Coord(x, y); Maze.Cells[x, y].onStack = false; --cellsOnStack; goto breakLoops; } } } breakLoops :; } } // remove the walls between the end squares Maze.Coord auxCurrentCell, auxNextCell; Maze.Wall auxWall; var endCoord = Maze.GetEndCoord(); for (int xAux = 0; xAux < Maze.EndSize.x; xAux++) { for (int yAux = 0; yAux < Maze.EndSize.y - 1; yAux++) { currentCell = new Maze.Coord(endCoord.x + xAux, endCoord.y + yAux); auxCurrentCell = currentCell; auxNextCell = new Maze.Coord(currentCell.x, currentCell.y + 1); auxWall = Maze.GetWallBetween(auxCurrentCell, auxNextCell); if (auxWall != Maze.Wall.None) { Maze.Cells[auxCurrentCell.x, auxCurrentCell.y].walls ^= auxWall; Maze.Cells[auxNextCell.x, auxNextCell.y].walls ^= Maze.GetOppositeWall(auxWall); } } } for (int xAux = 0; xAux < Maze.EndSize.x - 1; xAux++) { for (int yAux = 0; yAux < Maze.EndSize.y; yAux++) { currentCell = new Maze.Coord(endCoord.x + xAux, endCoord.y + yAux); auxCurrentCell = currentCell; auxNextCell = new Maze.Coord(currentCell.x + 1, currentCell.y); auxWall = Maze.GetWallBetween(auxCurrentCell, auxNextCell); if (auxWall != Maze.Wall.None) { Maze.Cells[auxCurrentCell.x, auxCurrentCell.y].walls ^= auxWall; Maze.Cells[auxNextCell.x, auxNextCell.y].walls ^= Maze.GetOppositeWall(auxWall); } } } }
public static void Generate(int width, int height) { int NumberOfCells, NumberOfWalls, NumberOfSets; int i, j, z, w; Cell[] cells; Wall[] walls; Room[] rooms; NumberOfCells = width * height; NumberOfWalls = ((width * (height - 1)) + (height * (width - 1))); NumberOfSets = NumberOfCells; cells = new Cell[NumberOfCells]; walls = new Wall[NumberOfWalls]; rooms = new Room[NumberOfSets]; // Create each Cell with its default ID in the Cells array for (i = 0; i < NumberOfCells; i++) { cells[i] = new Cell(i); //debug // Console.WriteLine(cells[i]); } // Create each with its default ID in the Sets array for (i = 0; i < NumberOfSets; i++) { rooms[i] = new Room(i, NumberOfCells); rooms[i].Cells[0] = cells[i]; // debug // Console.WriteLine(rooms[i]); } // Create each wall with its default ID in the walls array for (i = 0; i < NumberOfWalls; i++) { walls[i] = new Wall(i); } // Algorithm discovers if a wall is vertical // based on that each row starts by a multiple // of (width * 2) - 1 for (i = 0; i < NumberOfWalls; i++) { if (i == 0 || (i % ((width * 2) - 1) == 0)) { for (j = 0; j < (width - 1); j++) { walls[i + j].isFloor = false; } } // debug // Console.WriteLine(walls[i]); } // Now add two rooms to each wall // based on if it's a floor or not // need refactoring for (i = 0, z = 0, j = 0, w = width; i < NumberOfWalls; i++) { // Checks if it's a floor // and then, floor walls will begin // to increase from 0 and width // by 1 each time (width = 4 -> 0,4 (+1,+1) -> 1,5) if (walls[i].isFloor) { walls[i].Cells[0] = cells[j]; walls[i].Cells[1] = cells[w]; // debug // Console.WriteLine(walls[i] + " received " + j + " and " + w); j++; w++; } // And if it's not // it starts as 0 and 0+1 // but on the beginning of it each new row // (multiple of width*2 -1) // it increases +1 else { if (i != 0 && (i % ((width * 2) - 1) == 0)) { z++; } walls[i].Cells[0] = cells[z]; walls[i].Cells[1] = cells[z + 1]; // debug // Console.WriteLine(walls[i] + " received " + z + " and " + (z + 1)); z++; } } for (i = 0; i < width; i++) { Console.Write(" " + "_"); } foreach (Cell cell in cells) { if (cell.id % width == 0) { Console.WriteLine(" "); Console.Write("|"); } if (cell.id > (width * (height - 1)) || cell.id == NumberOfCells - 1) { Console.Write("_"); } foreach (Wall wall in walls) { if (wall.Contains(cell)) { if (wall.isFloor) { Console.Write("_"); } else { Console.Write("|"); } } } //if (cell.id % width == 1) //{ // Console.Write("|"); //} } }
public void ToggleWall(RaycastHit hit, bool insert) { var pillar1 = GetClosestPillar(hit.point); var pillar2 = GetClosestPillar(hit.point, pillar1); Vector3 bottomLeftPosition = new Vector3(Math.Min(pillar1.position.x, pillar2.position.x), 0, Math.Min(pillar1.position.z, pillar2.position.z)); Vector3 topRightPosition = new Vector3(Math.Max(pillar1.position.x, pillar2.position.x), 0, Math.Max(pillar1.position.z, pillar2.position.z)); var distanceToWallCenter = Vector3.Distance(hit.point, (topRightPosition + bottomLeftPosition) / 2); if (distanceToWallCenter > distanceToWallThreshold) { return; } Maze.Coord bottomLeftCoord = new Maze.Coord(0, 0); bottomLeftCoord.x = (int)Math.Round((bottomLeftPosition.x) * Maze.MazeSize.x / (Camera.main.transform.position.x * 2)); bottomLeftCoord.y = (int)Math.Round((bottomLeftPosition.z) * Maze.MazeSize.y / (Camera.main.transform.position.z * 2)); Vector3 diffPillar = pillar2.position - pillar1.position; Maze.Coord c0 = null; Maze.Coord c1 = null; Maze.Wall wall = Maze.Wall.None; // vertical wall if (diffPillar.x == 0 && bottomLeftCoord.x > 0 && bottomLeftCoord.y >= 0 && bottomLeftCoord.x < Maze.MazeSize.x && bottomLeftCoord.y < Maze.MazeSize.y) { c0 = new Maze.Coord(bottomLeftCoord.x - 1, bottomLeftCoord.y); c1 = new Maze.Coord(bottomLeftCoord.x, bottomLeftCoord.y); wall = Maze.Wall.East; } // horizontal wall else if (diffPillar.z == 0 && bottomLeftCoord.x >= 0 && bottomLeftCoord.y > 0 && bottomLeftCoord.x < Maze.MazeSize.x && bottomLeftCoord.y < Maze.MazeSize.y) { c0 = new Maze.Coord(bottomLeftCoord.x, bottomLeftCoord.y - 1); c1 = new Maze.Coord(bottomLeftCoord.x, bottomLeftCoord.y); wall = Maze.Wall.North; } if (c0 != null && c1 != null) { if (insert) { Maze.Cells[c0.x, c0.y].InsertWall(wall); Maze.Cells[c1.x, c1.y].InsertWall(Maze.GetOppositeWall(wall)); } else { Maze.Cells[c0.x, c0.y].RemoveWall(wall); Maze.Cells[c1.x, c1.y].RemoveWall(Maze.GetOppositeWall(wall)); } MazeSerializer.ResetMazeName(); FindObjectOfType <MazeBuilder>().Render(); } }