Я пытаюсь создать лабиринт из комнат и использую это руководство
Это то, чего я пытаюсь достичь. Вместо этого я получаю это:
Это то, что я сделал до сих пор (без ненужных частей)
using UnityEngine;
using Random = UnityEngine.Random;
using UnityEngine.Tilemaps;
using System.Collections.Generic;
using System.Linq;
public class MazeAndRoomGenerator : MonoBehaviour
{
TileType[,] levelWall;
int[,] regions;
int currentRegion = -1;
enum TileType { Floor, Wall }
// CONSTANTS
readonly static int[] north = { 0, 1 };
readonly static int[] south = { 0, -1 };
readonly static int[] east = { 1, 0 };
readonly static int[] west = { -1, 0 };
readonly static int[] northEast = { 1, 1 };
readonly static int[] northWest = { -1, 1 };
readonly static int[] southEast = { 1, -1 };
readonly static int[] southWest = { -1, -1 };
readonly static int[][] northCells = { north, northEast, northWest };
readonly static int[][] southCells = { south, southEast, southWest };
readonly static int[][] eastCells = { east, northEast, southEast };
readonly static int[][] westCells = { west, northWest, southWest };
public void GenerateMaze()
{
// Loop through all cells in the level and grow the maze in all parts that aren't assigned yet
for (int y = 0; y < mapSize; y += 2)
{
for (int x = 0; x < mapSize; x += 2)
{
if(levelWall[x,y] == TileType.Wall)
{
GrowMaze(x, y);
}
}
}
}
public void Carve(int x, int y)
{
levelWall[x,y] = TileType.Floor;
regions[x, y] = currentRegion;
}
public bool CanCarve(int[] pos, int[] dir)
{
// Returns false if the cell is already taken or out of map bounds
int x = pos[0] + dir[0] * 2;
int y = pos[1] + dir[1] * 2;
if (!InBounds(x, y)) { return false; }
int[][] checkCells = null;
if (dir == north) { checkCells = northCells; }
else if (dir == south) { checkCells = southCells; }
else if (dir == east) { checkCells = eastCells; }
else if (dir == west) { checkCells = westCells; }
else { Debug.LogError("Incorrect direction inputted"); }
foreach (int[] checkCell in checkCells)
{
int[] cell = { pos[0] + checkCell[0], pos[1] + checkCell[1] };
if (CanCarve(cell))
{
return false;
}
}
// All of the surrounding walls are available so return true
return true;
}
public bool CanCarve(int[] pos)
{
// Returns false if the cell is already taken or out of map bounds
int x = pos[0];
int y = pos[1];
// Checking if map is out of bounds
if (!InBounds(x, y))
{
return false;
}
// return True if the cell is a wall (1)
// false if the cell is a floor (0)
return (levelWall[x, y] == TileType.Wall);
}
public bool InBounds(int x, int y)
{
// Checking if map is out of bounds
if (!(0 < x) || !(x < mapSize) ||
!(0 < y) || !(y < mapSize))
{
return false;
}
else return true;
}
public void GrowMaze(int startX, int startY)
{
/*
* RULES:
* If any of the neighbour cells to start point (CanCarve == false) are floor then stop.
* Take a random available direction and start carving.
* For each cell that is carved first check if the cell in front of it (travelling in the same direction)
* and the cells to the left and right of the cell is carvable.
* If isn't then remove that direction from available directions and pick new direction from original cell.
* Repeat until no available directions left
*/
int[][] directions = { north, south, east, west };
int[][] neighbourCells = { north, south, east, west, northEast, northWest, southEast, southWest };
int[] start = { startX, startY };
List<int[]> cells = new List<int[]>();
int[] lastDirection = null;
// Check if starting point is valid
foreach (int[] direction in neighbourCells)
{
int[] checkCell = { start[0] + direction[0], start[1] + direction[1] };
if (!CanCarve(checkCell))
{
// Throw out start cell and don't start maze from there
return;
}
}
// Start a new region for the new maze region
StartRegion();
Carve(start[0], start[1]);
cells.Add(start);
// While there are available cells to travel to run script
while (cells.Count > 0 && cells.Count < 10000)
{
int[] cell = cells[cells.Count - 1];
List<int[]> unmadeCells = new List<int[]>();
foreach (int[] direction in directions)
{
int[] checkCell = { cell[0] + direction[0], cell[1] + direction[1] };
if (CanCarve(checkCell, direction))
{
unmadeCells.Add(direction);
}
}
// If there are available cells to travel to run script
if (unmadeCells.Count > 0)
{
// Prefer to continue in the last direction travelling if available
// Random chance for it to choose a different direction
int[] direction;
if (unmadeCells.Contains(lastDirection)
&& (Random.value > (windingChance/100)) )
{
direction = lastDirection;
}
else
{
direction = unmadeCells[Random.Range(0, unmadeCells.Count)];
}
int[] newCell;
newCell = new int[] { cell[0] + direction[0], cell[1] + direction[1] };
Carve(newCell[0], newCell[1]);
// Adds new cell onto stack and script will repeat with this cell until it has no possible directions to travel
cells.Add(newCell);
lastDirection = direction;
}
else
{
cells.RemoveAt(cells.Count - 1);
lastDirection = null;
}
}
}
}
У меня есть идея, что это как-то связано с тем, что массив cells
продолжает увеличиваться и поэтому застрял в al oop, поэтому я добавил ограничение на количество ячеек, в то время как l oop для отладки.
Мои правила для лабиринта таковы:
- Если любая из соседних ячеек для начальной точки (CanCarve == false) имеет нижний этаж, то остановитесь.
- Выберите произвольно доступное направление и начните вырезать.
- Для каждой вырезанной ячейки сначала проверьте, находится ли ячейка перед ней (движется в том же направлении) и ячейки слева и право на клетку резное. Если это не так, удалите это направление из доступных направлений и выберите новое направление из исходной ячейки.
- Повторяйте, пока не осталось доступных направлений
Я был бы очень признателен за любую помощь. Я рвал на себе волосы:)