holopy3/Assets/Scripts/RecursiveBacktrackerChris.cs

167 lines
4.9 KiB
C#
Raw Normal View History

2020-12-10 14:25:12 +00:00
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  cant 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)];
}
}
}