Skip to content

Instantly share code, notes, and snippets.

@celechii
Last active November 13, 2020 01:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save celechii/b3c0ff6351bbf6fb026990de4fae7c5c to your computer and use it in GitHub Desktop.
Save celechii/b3c0ff6351bbf6fb026990de4fae7c5c to your computer and use it in GitHub Desktop.
using UnityEngine;
public class DirectionMaze : MonoBehaviour {
[System.Flags]
public enum Direction {
Up = 1 << 0,
Down = 1 << 1,
Left = 1 << 2,
Right = 1 << 3
}
public Vector2Int mazeSize = new Vector2Int(15, 15);
[SerializeField]
private bool drawGizmos = true;
private Direction[, ] maze;
private Vector2Int prevSize; // delete this, the OnValidate() method, n the OnDrawGizmos() method if u dont wanna preview it in the editor
private bool[, ] visited;
[ContextMenu("Generate Maze")]
public Direction[, ] GenerateMaze() {
maze = new Direction[mazeSize.x, mazeSize.y];
visited = new bool[mazeSize.x, mazeSize.y];
// random starting pos on an odd index position
Vector2Int startPos = new Vector2Int(Random.Range(0, (int)(mazeSize.x / 2f)), Random.Range(0, (int)(mazeSize.y / 2f)));
startPos *= 2;
startPos += Vector2Int.one;
visited[startPos.x, startPos.y] = true;
RecurseMaze(startPos.x, startPos.y);
return maze;
}
/// <summary>
/// Returns an array of 4 booleans in the order up, down, left, right.
/// </summary>
/// <param name="pos">The position in the maze.</param>
public bool[] GetExitsAt(Vector2Int pos) => GetExitsAt(pos.x, pos.y);
/// <summary>
/// Returns an array of 4 booleans in the order up, down, left, right.
/// </summary>
/// <param name="x">The x position in the maze.</param>
/// <param name="y">The y position in the maze.</param>
public bool[] GetExitsAt(int x, int y) {
Direction exits = maze[x, y];
return new bool[] {
exits.HasFlag(Direction.Up),
exits.HasFlag(Direction.Down),
exits.HasFlag(Direction.Left),
exits.HasFlag(Direction.Right)
};
}
private void OnValidate() {
if (!drawGizmos)
return;
Vector2Int change = mazeSize - prevSize;
if (mazeSize.x <= 2)
mazeSize.x = 2;
if (mazeSize.y <= 2)
mazeSize.y = 2;
GenerateMaze();
prevSize = mazeSize;
}
private void RecurseMaze(int xPos, int yPos, Direction comingFrom = 0) {
visited[xPos, yPos] = true;
if ((int)comingFrom != 0)
AddDirection(xPos, yPos, comingFrom);
// shuffle the order u check the directions in
int[] randomDirs = new int[] {-1, -1, -1, -1 };
for (int i = 0; i < randomDirs.Length; i++) {
int arrayPos;
do {
arrayPos = Random.Range(0, 4);
} while (randomDirs[arrayPos] != -1);
randomDirs[arrayPos] = i;
}
for (int i = 0; i < randomDirs.Length; i++) {
// only run in this direction if its a valid one
if (IsValidDirection(randomDirs[i], xPos, yPos)) {
if (randomDirs[i] == 0) { // go up
AddDirection(xPos, yPos, Direction.Up);
RecurseMaze(xPos, yPos + 1, Direction.Down);
} else if (randomDirs[i] == 1) { // go down
AddDirection(xPos, yPos, Direction.Down);
RecurseMaze(xPos, yPos - 1, Direction.Up);
} else if (randomDirs[i] == 2) { // go left
AddDirection(xPos, yPos, Direction.Left);
RecurseMaze(xPos - 1, yPos, Direction.Right);
} else if (randomDirs[i] == 3) { // go right
AddDirection(xPos, yPos, Direction.Right);
RecurseMaze(xPos + 1, yPos, Direction.Left);
}
}
}
}
private void AddDirection(int xPos, int yPos, Direction direction) => maze[xPos, yPos] |= direction;
private bool IsValidDirection(int dir, int x, int y) {
if (dir == 0)
return IsValidPosition(x, y + 1); // up
if (dir == 1)
return IsValidPosition(x, y - 1); // down
if (dir == 2)
return IsValidPosition(x - 1, y); // left
if (dir == 3)
return IsValidPosition(x + 1, y); // right
return false;
bool IsValidPosition(int xPos, int yPos) {
return xPos >= 0 && xPos < mazeSize.x && yPos >= 0 && yPos < mazeSize.y && !visited[xPos, yPos];
}
}
private void OnDrawGizmos() {
if (!drawGizmos)
return;
if (maze == null)
GenerateMaze();
Vector2 offset = (Vector2)mazeSize / 2f;
for (int x = 0; x < mazeSize.x; x++) {
for (int y = 0; y < mazeSize.y; y++) {
Gizmos.color = Color.black;
Vector2 pos = new Vector2(x, y) - offset;
Gizmos.DrawWireCube(pos, Vector2.one);
Gizmos.color = Color.green;
if (maze[x, y].HasFlag(Direction.Up))
Gizmos.DrawRay(pos, Vector2.up);
if (maze[x, y].HasFlag(Direction.Down))
Gizmos.DrawRay(pos, Vector2.down);
if (maze[x, y].HasFlag(Direction.Left))
Gizmos.DrawRay(pos, Vector2.left);
if (maze[x, y].HasFlag(Direction.Right))
Gizmos.DrawRay(pos, Vector2.right);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment