UnityGame/Assets/Scripts/MazeGenerator.cs

241 lines
8.3 KiB
C#
Raw Permalink Normal View History

2024-10-27 10:53:47 +03:00
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MazeGenerator : MonoBehaviour
{
public int mazeWidth = 20; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public int mazeHeight = 20; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public float cellSize = 1.5f; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public float wallThickness = 0f; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
public float wallHeight = 1f; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
public GameObject northPrefab; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
public GameObject southPrefab; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
public GameObject eastPrefab; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
public GameObject westPrefab; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
public GameObject floorPrefab1; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
public GameObject floorPrefab2; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
public GameObject floorPrefab3; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
public GameObject floorPrefab4; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
public GameObject upperPrefab; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
public Transform mazeParent; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public GameObject LightStick; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public Vector3 mazeOffset; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>)
private Cell[,] grid;
void Start()
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
float doorX = 5f;
float doorZ = 0f;
float passageWidth = 2f;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
InitializeMaze();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
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();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
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);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 4-<2D> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
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;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
float halfCell = cellSize / 2f;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
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;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
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;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
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;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
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)
{
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Destroy(current.westWall);
Destroy(neighbor.eastWall);
}
else if (dx == -1)
{
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Destroy(current.eastWall);
Destroy(neighbor.westWall);
}
if (dz == 1)
{
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD>
Destroy(current.southWall);
Destroy(neighbor.northWall);
}
else if (dz == -1)
{
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Destroy(current.northWall);
Destroy(neighbor.southWall);
}
}
void CreateMazeEntrance()
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
float passageWidth = 2f;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int entranceXIndex = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> x
int entranceZStart = 0;
int passageCells = Mathf.CeilToInt(passageWidth / cellSize);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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;
}