241 lines
8.3 KiB
C#
241 lines
8.3 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
public class MazeGenerator : MonoBehaviour
|
|
{
|
|
public int mazeWidth = 20; // Øèðèíà ëàáèðèíòà â ÿ÷åéêàõ
|
|
public int mazeHeight = 20; // Âûñîòà ëàáèðèíòà â ÿ÷åéêàõ
|
|
public float cellSize = 1.5f; // Ðàçìåð êàæäîé ÿ÷åéêè
|
|
|
|
public float wallThickness = 0f; // Òîëùèíà ñòåí
|
|
public float wallHeight = 1f; // Òîëùèíà ñòåí
|
|
|
|
public GameObject northPrefab; // Ïðåôàá ñòåíû
|
|
public GameObject southPrefab; // Ïðåôàá ñòåíû
|
|
public GameObject eastPrefab; // Ïðåôàá ñòåíû
|
|
public GameObject westPrefab; // Ïðåôàá ñòåíû
|
|
public GameObject floorPrefab1; // Ïðåôàá ïîëà
|
|
public GameObject floorPrefab2; // Ïðåôàá ïîëà
|
|
public GameObject floorPrefab3; // Ïðåôàá ïîëà
|
|
public GameObject floorPrefab4; // Ïðåôàá ïîëà
|
|
public GameObject upperPrefab; // Ïðåôàá ïîëà
|
|
public Transform mazeParent; // Ðîäèòåëüñêèé îáúåêò äëÿ ýëåìåíòîâ ëàáèðèíòà
|
|
|
|
public GameObject LightStick; //ïðåôàá ÔÎÍÀÐß ÑÎ ÑÂÅÒÎÌ
|
|
|
|
public Vector3 mazeOffset; // Ñìåùåíèå ëàáèðèíòà (óñòàíîâèì ïîçæå)
|
|
|
|
private Cell[,] grid;
|
|
|
|
void Start()
|
|
{
|
|
// Ïàðàìåòðû äâåðè
|
|
float doorX = 5f;
|
|
float doorZ = 0f;
|
|
float passageWidth = 2f;
|
|
|
|
// Íàñòðîéêà ñìåùåíèÿ ëàáèðèíòà
|
|
|
|
InitializeMaze();
|
|
|
|
// Íà÷èíàåì ãåíåðàöèþ ëàáèðèíòà ñ ïðîèçâîëüíîé òî÷êè
|
|
int startX = Random.Range(0, mazeWidth);
|
|
int startZ = Random.Range(0, mazeHeight);
|
|
GenerateMaze(startX, startZ);
|
|
|
|
CreateMazeEntrance();
|
|
CreateMazeExit();
|
|
}
|
|
|
|
void InitializeMaze()
|
|
{
|
|
grid = new Cell[mazeWidth, mazeHeight];
|
|
|
|
for (int x = 0; x < mazeWidth; x++)
|
|
{
|
|
for (int z = 0; z < mazeHeight; z++)
|
|
{
|
|
Cell cell = new Cell();
|
|
|
|
// Ïîçèöèÿ öåíòðà ÿ÷åéêè
|
|
Vector3 cellPos = new Vector3(x * cellSize, 0, z * cellSize) + mazeOffset;
|
|
Vector3 upperPos = new Vector3(x * cellSize, 10, z * cellSize) + mazeOffset;
|
|
Vector3 bottPos = new Vector3(x * cellSize, 0.3f, z * cellSize) + mazeOffset;
|
|
Vector3 backupperPos = new Vector3(x * cellSize, 10.1f, z * cellSize) + mazeOffset;
|
|
Vector3 lightPos = new Vector3(x * cellSize -3, 0, z * cellSize - 3) + mazeOffset;
|
|
|
|
// Ñëó÷àéíàÿ ãåíåðàöèÿ ïîëà
|
|
int floorType = Random.Range(1, 5);
|
|
switch (floorType)
|
|
{
|
|
case 1:
|
|
cell.floor = Instantiate(floorPrefab1, bottPos, Quaternion.identity, mazeParent);
|
|
break;
|
|
case 2:
|
|
cell.floor = Instantiate(floorPrefab2, bottPos, Quaternion.identity, mazeParent);
|
|
break;
|
|
case 3:
|
|
cell.floor = Instantiate(floorPrefab3, bottPos, Quaternion.identity, mazeParent);
|
|
break;
|
|
case 4:
|
|
cell.floor = Instantiate(floorPrefab4, bottPos, Quaternion.identity, mazeParent);
|
|
break;
|
|
}
|
|
cell.floor.transform.localScale = new Vector3(0.904f, 4f, 0.901f);
|
|
|
|
// Äîáàâëåíèå ôîíàðåé â êàæäîì 4-ì ñòîëáöå è ñòðîêå
|
|
if (((x % 3 == 0 && z % 3 == 0 && Random.value < 0.65f) || (Random.value < 0.1f)) && (x > 2 && z > 2))
|
|
{
|
|
cell.lightstick = Instantiate(LightStick, lightPos, Quaternion.identity, mazeParent);
|
|
}
|
|
|
|
// Ñîçäàíèå ïîëà
|
|
cell.upper = Instantiate(upperPrefab, upperPos, Quaternion.identity, mazeParent);
|
|
cell.upper.transform.localScale = new Vector3(1f, -3f, 1f);
|
|
|
|
cell.upper = Instantiate(upperPrefab, backupperPos, Quaternion.identity, mazeParent);
|
|
cell.upper.transform.localScale = new Vector3(1f, 1f, 1f);
|
|
|
|
southPrefab = northPrefab;
|
|
westPrefab = northPrefab;
|
|
eastPrefab = northPrefab;
|
|
|
|
// Ïàðàìåòðû ñòåí
|
|
|
|
float halfCell = cellSize / 2f;
|
|
|
|
// Ñîçäàíèå ñåâåðíîé ñòåíû
|
|
Vector3 northWallPos = cellPos + new Vector3(0, 1, halfCell);
|
|
GameObject northWall = Instantiate(northPrefab, northWallPos, Quaternion.identity, mazeParent);
|
|
northWall.transform.localScale = new Vector3(0.8f, 1, 1);
|
|
cell.northWall = northWall;
|
|
|
|
// Ñîçäàíèå þæíîé ñòåíû
|
|
Vector3 southWallPos = cellPos + new Vector3(0, 1, -halfCell);
|
|
GameObject southWall = Instantiate(southPrefab, southWallPos, Quaternion.identity, mazeParent);
|
|
southWall.transform.localScale = new Vector3(0.8f, 1, 1);
|
|
cell.southWall = southWall;
|
|
|
|
// Ñîçäàíèå âîñòî÷íîé ñòåíû
|
|
Vector3 eastWallPos = cellPos + new Vector3(halfCell, 1, 0);
|
|
GameObject eastWall = Instantiate(eastPrefab, eastWallPos, Quaternion.identity, mazeParent);
|
|
eastWall.transform.Rotate(0, 90, 0);
|
|
eastWall.transform.localScale = new Vector3(0.8f, 1, 1);
|
|
cell.eastWall = eastWall;
|
|
|
|
// Ñîçäàíèå çàïàäíîé ñòåíû
|
|
Vector3 westWallPos = cellPos + new Vector3(-halfCell, 1, 0);
|
|
GameObject westWall = Instantiate(westPrefab, westWallPos, Quaternion.identity, mazeParent);
|
|
westWall.transform.Rotate(0, 90, 0);
|
|
westWall.transform.localScale = new Vector3(0.8f, 1, 1);
|
|
cell.westWall = westWall;
|
|
|
|
grid[x, z] = cell;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GenerateMaze(int x, int z)
|
|
{
|
|
grid[x, z].visited = true;
|
|
|
|
List<Vector2Int> neighbors = GetUnvisitedNeighbors(x, z);
|
|
|
|
while (neighbors.Count > 0)
|
|
{
|
|
Vector2Int chosenNeighbor = neighbors[Random.Range(0, neighbors.Count)];
|
|
int nx = chosenNeighbor.x;
|
|
int nz = chosenNeighbor.y;
|
|
|
|
if (!grid[nx, nz].visited)
|
|
{
|
|
RemoveWalls(grid[x, z], grid[nx, nz], x - nx, z - nz);
|
|
GenerateMaze(nx, nz);
|
|
}
|
|
|
|
neighbors = GetUnvisitedNeighbors(x, z);
|
|
}
|
|
}
|
|
|
|
List<Vector2Int> GetUnvisitedNeighbors(int x, int z)
|
|
{
|
|
List<Vector2Int> neighbors = new List<Vector2Int>();
|
|
|
|
if (x > 0 && !grid[x - 1, z].visited)
|
|
neighbors.Add(new Vector2Int(x - 1, z));
|
|
if (x < mazeWidth - 1 && !grid[x + 1, z].visited)
|
|
neighbors.Add(new Vector2Int(x + 1, z));
|
|
if (z > 0 && !grid[x, z - 1].visited)
|
|
neighbors.Add(new Vector2Int(x, z - 1));
|
|
if (z < mazeHeight - 1 && !grid[x, z + 1].visited)
|
|
neighbors.Add(new Vector2Int(x, z + 1));
|
|
|
|
return neighbors;
|
|
}
|
|
|
|
void RemoveWalls(Cell current, Cell neighbor, int dx, int dz)
|
|
{
|
|
if (dx == 1)
|
|
{
|
|
// Ñîñåä íà çàïàäå
|
|
Destroy(current.westWall);
|
|
Destroy(neighbor.eastWall);
|
|
}
|
|
else if (dx == -1)
|
|
{
|
|
// Ñîñåä íà âîñòîêå
|
|
Destroy(current.eastWall);
|
|
Destroy(neighbor.westWall);
|
|
}
|
|
if (dz == 1)
|
|
{
|
|
// Ñîñåä íà þãå
|
|
Destroy(current.southWall);
|
|
Destroy(neighbor.northWall);
|
|
}
|
|
else if (dz == -1)
|
|
{
|
|
// Ñîñåä íà ñåâåðå
|
|
Destroy(current.northWall);
|
|
Destroy(neighbor.southWall);
|
|
}
|
|
}
|
|
|
|
void CreateMazeEntrance()
|
|
{
|
|
// Ïàðàìåòðû äâåðè
|
|
float passageWidth = 2f;
|
|
|
|
// Ðàñ÷åò èíäåêñîâ ÿ÷ååê äëÿ ïðîõîäà
|
|
int entranceXIndex = 0; // Íà÷àëî ëàáèðèíòà ïî x
|
|
int entranceZStart = 0;
|
|
int passageCells = Mathf.CeilToInt(passageWidth / cellSize);
|
|
|
|
// Ñîçäàåì âõîä â ëàáèðèíò
|
|
for (int i = 0; i < passageCells; i++)
|
|
{
|
|
int z = entranceZStart + i;
|
|
|
|
if (z >= 0 && z < mazeHeight)
|
|
{
|
|
Destroy(grid[entranceXIndex, z].westWall);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CreateMazeExit()
|
|
{
|
|
int exitXIndex = mazeWidth - 1;
|
|
int exitZIndex = Random.Range(0, mazeHeight);
|
|
|
|
Destroy(grid[exitXIndex, exitZIndex].eastWall);
|
|
}
|
|
}
|
|
|
|
public class Cell
|
|
{
|
|
public bool visited = false;
|
|
public GameObject northWall, southWall, eastWall, westWall, floor, upper, lightstick;
|
|
}
|