166 lines
4.9 KiB
C#
166 lines
4.9 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
public class RecursiveBacktrackerChris : MonoBehaviour
|
||
{
|
||
private MyTile[,] levelTiles;
|
||
|
||
private GameObject level;
|
||
private Vector2Int currentPos;
|
||
private Stack<Vector2Int> positions;
|
||
public GameObject Ground;
|
||
public GameObject Wall;
|
||
public int MapSize;
|
||
public int StepLength;
|
||
|
||
private void Awake()
|
||
{
|
||
level = new GameObject("Level");
|
||
positions = new Stack<Vector2Int>();
|
||
|
||
CreateLevel(MapSize);
|
||
MakeMaze();
|
||
}
|
||
|
||
private void CreateLevel(int size)
|
||
{
|
||
levelTiles = new MyTile[size, size];
|
||
|
||
for (int i = 0; i < size; i++)
|
||
{
|
||
for (int j = 0; j < size; j++)
|
||
{
|
||
//GameObject temp = GameObject.Instantiate(Wall);
|
||
GameObject temp = GameObject.CreatePrimitive(PrimitiveType.Cube); //kann verwendet werden, wenn du keine eigenen Assets für Wall hast.
|
||
temp.transform.position = new Vector3(i, j, 0);
|
||
temp.transform.SetParent(level.transform);
|
||
levelTiles[i, j] = temp.AddComponent<MyTile>();
|
||
|
||
// frame as ground can’t dig there
|
||
if (i == 0 || j == 0 || i == size - 1 || j == size - 1)
|
||
{
|
||
levelTiles[i, j].type = MyTile.TileType.Ground;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void MakeMaze()
|
||
{
|
||
currentPos = GetRandomStartPosition();
|
||
SetTileType(currentPos, MyTile.TileType.Ground);
|
||
positions.Push(currentPos);
|
||
|
||
while (positions.Count > 0)
|
||
{
|
||
Vector2Int digDirection = GetRandomDirection(currentPos);
|
||
while (digDirection == Vector2Int.zero)
|
||
{
|
||
positions.Pop();
|
||
if (positions.Count == 0)
|
||
return;
|
||
currentPos = positions.Peek();
|
||
digDirection = GetRandomDirection(currentPos);
|
||
}
|
||
currentPos = DigDirection(currentPos, digDirection, StepLength);
|
||
positions.Push(currentPos);
|
||
}
|
||
}
|
||
|
||
// zufälligen Startpunkt wählen
|
||
private Vector2Int GetRandomStartPosition()
|
||
{
|
||
int startX = Random.Range(1, MapSize - 1);
|
||
int startY = Random.Range(1, MapSize - 1);
|
||
|
||
startX = startX % 2 == 0 ? startX - 1 : startX;
|
||
startY = startY % 2 == 0 ? startY - 1 : startY;
|
||
|
||
Vector2Int startPos = new Vector2Int(startX, startY);
|
||
return startPos;
|
||
}
|
||
|
||
private MyTile GetNeighbor(Vector2Int position, Vector2Int direction)
|
||
{
|
||
MyTile temp = null;
|
||
try
|
||
{
|
||
temp = levelTiles[position.x + StepLength * direction.x,
|
||
position.y + StepLength * direction.y];
|
||
|
||
if (temp.type == MyTile.TileType.Ground)
|
||
{
|
||
temp = null;
|
||
}
|
||
}
|
||
catch (System.IndexOutOfRangeException e)
|
||
{
|
||
Debug.LogWarning(e.Message);
|
||
}
|
||
return temp;
|
||
}
|
||
|
||
private Vector2Int DigDirection(Vector2Int position, Vector2Int direction, int stepLength)
|
||
{
|
||
for (int i = 0; i <= stepLength; i++)
|
||
{
|
||
SetTileType(position + i * direction, MyTile.TileType.Ground);
|
||
}
|
||
return position + stepLength * direction;
|
||
}
|
||
|
||
private void SetTileType(Vector2Int position, MyTile.TileType tileType)
|
||
{
|
||
try
|
||
{
|
||
levelTiles[position.x, position.y].type = tileType;
|
||
if (tileType == MyTile.TileType.Ground)
|
||
{
|
||
Destroy(levelTiles[position.x, position.y].gameObject);
|
||
GameObject temp = GameObject.Instantiate(Ground,
|
||
new Vector3(position.x, position.y, 0),
|
||
Quaternion.identity);
|
||
temp.transform.SetParent(level.transform);
|
||
}
|
||
}
|
||
catch (System.IndexOutOfRangeException e)
|
||
{
|
||
Debug.LogWarning($"{e.Message}: position = {position}");
|
||
}
|
||
}
|
||
|
||
// zufällige Richtung graben
|
||
private Vector2Int GetRandomDirection(Vector2Int position)
|
||
{
|
||
List<Vector2Int> directions = new List<Vector2Int>();
|
||
|
||
if (GetNeighbor(position, Vector2Int.right) != null)
|
||
{
|
||
directions.Add(Vector2Int.right);
|
||
}
|
||
if (GetNeighbor(position, Vector2Int.left) != null)
|
||
{
|
||
directions.Add(Vector2Int.left);
|
||
}
|
||
if (GetNeighbor(position, Vector2Int.down) != null)
|
||
{
|
||
directions.Add(Vector2Int.down);
|
||
}
|
||
if (GetNeighbor(position, Vector2Int.up) != null)
|
||
{
|
||
directions.Add(Vector2Int.up);
|
||
}
|
||
|
||
// wenn Sackgasse, Position vom Stack nehmen
|
||
if (directions.Count == 0)
|
||
{
|
||
// keine Nachbarn gefunden
|
||
return Vector2Int.zero;
|
||
}
|
||
else
|
||
{
|
||
return directions[Random.Range(0, directions.Count)];
|
||
}
|
||
}
|
||
}
|