Merge branch 'main' of https://scove-vault.duckdns.org/scove/HALLUCINATION
This commit is contained in:
@@ -1,51 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class Crawler : Maze
|
||||
{
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
//for (int i = 0; i < 2; i++)
|
||||
// CrawlV();
|
||||
|
||||
//for(int i = 0; i < 3; i++)
|
||||
// CrawlH();
|
||||
}
|
||||
|
||||
void CrawlV()
|
||||
{
|
||||
bool done = false;
|
||||
int x = Random.Range(1,width-1);
|
||||
int z = 1;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
map[x, z] = 0;
|
||||
if (Random.Range(0, 100) < 50)
|
||||
x += Random.Range(-1, 2);
|
||||
else
|
||||
z += Random.Range(0, 2);
|
||||
done |= (x < 1 || x >= width-1 || z < 1 || z >= depth-1);
|
||||
}
|
||||
}
|
||||
|
||||
void CrawlH()
|
||||
{
|
||||
bool done = false;
|
||||
int x = 1;
|
||||
int z = Random.Range(1,depth-1);
|
||||
|
||||
while (!done)
|
||||
{
|
||||
map[x, z] = 0;
|
||||
if (Random.Range(0, 100) < 50)
|
||||
x += Random.Range(0, 2);
|
||||
else
|
||||
z += Random.Range(-1, 2);
|
||||
done |= (x < 1 || x >= width-1 || z < 1 || z >= depth-1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b5776943e6d841879f829c725bf4e6b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
77
Assets/Scripts/GameSetup/Maze/CrawlerAlgorithm.cs
Normal file
77
Assets/Scripts/GameSetup/Maze/CrawlerAlgorithm.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Hallucinate.GameSetup.Maze
|
||||
{
|
||||
public class CrawlerAlgorithm : IMazeAlgorithm
|
||||
{
|
||||
private const int CrawlChance = 50;
|
||||
private const int MinBoundary = 1;
|
||||
private const int VerticalCrawlerCount = 3;
|
||||
private const int HorizontalCrawlerCount = 3;
|
||||
|
||||
public void Generate(MazeGrid grid)
|
||||
{
|
||||
for (int i = 0; i < VerticalCrawlerCount; i++) CrawlV(grid, 0);
|
||||
for (int i = 0; i < HorizontalCrawlerCount; i++) CrawlH(grid, 0);
|
||||
}
|
||||
|
||||
public IEnumerator GenerateStepByStep(MazeGrid grid, float interval)
|
||||
{
|
||||
for (int i = 0; i < VerticalCrawlerCount; i++) yield return CrawlV(grid, interval);
|
||||
for (int i = 0; i < HorizontalCrawlerCount; i++) yield return CrawlH(grid, interval);
|
||||
}
|
||||
|
||||
private IEnumerator CrawlV(MazeGrid grid, float interval)
|
||||
{
|
||||
bool done = false;
|
||||
int x = Random.Range(MinBoundary, grid.Width - MinBoundary);
|
||||
int z = MinBoundary;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
grid.SetCell(x, z, MazeCellType.Processing);
|
||||
if (interval > 0) yield return new WaitForSeconds(interval);
|
||||
|
||||
grid.SetCell(x, z, MazeCellType.Corridor);
|
||||
|
||||
if (Random.Range(0, 100) < CrawlChance)
|
||||
{
|
||||
x += Random.Range(-1, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
z += Random.Range(0, 2);
|
||||
}
|
||||
|
||||
done |= (x < MinBoundary || x >= grid.Width - MinBoundary || z < MinBoundary || z >= grid.Depth - MinBoundary);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator CrawlH(MazeGrid grid, float interval)
|
||||
{
|
||||
bool done = false;
|
||||
int x = MinBoundary;
|
||||
int z = Random.Range(MinBoundary, grid.Depth - MinBoundary);
|
||||
|
||||
while (!done)
|
||||
{
|
||||
grid.SetCell(x, z, MazeCellType.Processing);
|
||||
if (interval > 0) yield return new WaitForSeconds(interval);
|
||||
|
||||
grid.SetCell(x, z, MazeCellType.Corridor);
|
||||
|
||||
if (Random.Range(0, 100) < CrawlChance)
|
||||
{
|
||||
x += Random.Range(0, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
z += Random.Range(-1, 2);
|
||||
}
|
||||
|
||||
done |= (x < MinBoundary || x >= grid.Width - MinBoundary || z < MinBoundary || z >= grid.Depth - MinBoundary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/GameSetup/Maze/CrawlerAlgorithm.cs.meta
Normal file
2
Assets/Scripts/GameSetup/Maze/CrawlerAlgorithm.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd419f9be92beac48b6f551063165e1f
|
||||
@@ -1,21 +1,25 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public static class Extensions
|
||||
namespace Hallucinate.GameSetup.Maze.Extensions
|
||||
{
|
||||
private static System.Random rng = new System.Random();
|
||||
public static void Shuffle<T>(this IList<T> list)
|
||||
public static class ListExtensions
|
||||
{
|
||||
int n = list.Count;
|
||||
while (n > 1)
|
||||
private static System.Random _rng = new System.Random();
|
||||
|
||||
/// <summary>
|
||||
/// Shuffles a list using the Fisher-Yates algorithm.
|
||||
/// </summary>
|
||||
public static void Shuffle<T>(this IList<T> list)
|
||||
{
|
||||
n--;
|
||||
int k = rng.Next(n + 1);
|
||||
T value = list[k];
|
||||
list[k] = list[n];
|
||||
list[n] = value;
|
||||
int n = list.Count;
|
||||
while (n > 1)
|
||||
{
|
||||
n--;
|
||||
int k = _rng.Next(n + 1);
|
||||
T value = list[k];
|
||||
list[k] = list[n];
|
||||
list[n] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d9791b1b03c14f16a245b2d4577c5f9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
guid: 7d9791b1b03c14f16a245b2d4577c5f9
|
||||
8
Assets/Scripts/GameSetup/Maze/Interfaces.meta
Normal file
8
Assets/Scripts/GameSetup/Maze/Interfaces.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e1bb9cd9af7ffe40ad1a740c3c30dd6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
19
Assets/Scripts/GameSetup/Maze/Interfaces/IMazeAlgorithm.cs
Normal file
19
Assets/Scripts/GameSetup/Maze/Interfaces/IMazeAlgorithm.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace Hallucinate.GameSetup.Maze
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for all maze generation algorithms.
|
||||
/// Supports both immediate and step-by-step (animated) generation.
|
||||
/// </summary>
|
||||
public interface IMazeAlgorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates the maze immediately in one frame.
|
||||
/// </summary>
|
||||
void Generate(MazeGrid grid);
|
||||
|
||||
/// <summary>
|
||||
/// Generates the maze step-by-step for visualization.
|
||||
/// </summary>
|
||||
System.Collections.IEnumerator GenerateStepByStep(MazeGrid grid, float interval);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 46b6a7796ba3c494581e4dcb884da064
|
||||
32
Assets/Scripts/GameSetup/Maze/MapLocation.cs
Normal file
32
Assets/Scripts/GameSetup/Maze/MapLocation.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
namespace Hallucinate.GameSetup.Maze
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a 2D coordinate on the maze grid.
|
||||
/// Used as a lightweight value type to avoid GC allocations.
|
||||
/// </summary>
|
||||
public readonly struct MapLocation
|
||||
{
|
||||
public readonly int x;
|
||||
public readonly int z;
|
||||
|
||||
public MapLocation(int _x, int _z)
|
||||
{
|
||||
x = _x;
|
||||
z = _z;
|
||||
}
|
||||
|
||||
// Static predefined directions to eliminate magic numbers in algorithms
|
||||
public static MapLocation Right => new MapLocation(1, 0);
|
||||
public static MapLocation Left => new MapLocation(-1, 0);
|
||||
public static MapLocation Up => new MapLocation(0, 1);
|
||||
public static MapLocation Down => new MapLocation(0, -1);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of all 4 cardinal directions.
|
||||
/// </summary>
|
||||
public static System.Collections.Generic.List<MapLocation> Directions => new System.Collections.Generic.List<MapLocation>
|
||||
{
|
||||
Right, Up, Left, Down
|
||||
};
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/GameSetup/Maze/MapLocation.cs.meta
Normal file
2
Assets/Scripts/GameSetup/Maze/MapLocation.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 987a7c46c96326a44b3a5f179fe61161
|
||||
@@ -1,100 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MapLocation
|
||||
{
|
||||
public int x;
|
||||
public int z;
|
||||
|
||||
public MapLocation(int _x, int _z)
|
||||
{
|
||||
x = _x;
|
||||
z = _z;
|
||||
}
|
||||
}
|
||||
|
||||
public class Maze : MonoBehaviour
|
||||
{
|
||||
public List<MapLocation> directions = new List<MapLocation>() {
|
||||
new MapLocation(1,0),
|
||||
new MapLocation(0,1),
|
||||
new MapLocation(-1,0),
|
||||
new MapLocation(0,-1) };
|
||||
public int width = 30; //x length
|
||||
public int depth = 30; //z length
|
||||
public byte[,] map;
|
||||
public int scale = 6;
|
||||
public Transform _mapParentObjet;
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
InitialiseMap();
|
||||
Generate();
|
||||
DrawMap();
|
||||
}
|
||||
|
||||
void InitialiseMap()
|
||||
{
|
||||
map = new byte[width,depth];
|
||||
for (int z = 0; z < depth; z++)
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
map[x, z] = 1; //1 = wall 0 = corridor
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Generate()
|
||||
{
|
||||
for (int z = 0; z < depth; z++)
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
if(Random.Range(0,100) < 50)
|
||||
map[x, z] = 0; //1 = wall 0 = corridor
|
||||
}
|
||||
}
|
||||
|
||||
void DrawMap()
|
||||
{
|
||||
for (int z = 0; z < depth; z++)
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
if (map[x, z] == 1)
|
||||
{
|
||||
Vector3 pos = new Vector3(x * scale, 0, z * scale);
|
||||
GameObject wall = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
wall.transform.localScale = new Vector3(scale, scale, scale);
|
||||
wall.transform.position = pos;
|
||||
wall.transform.SetParent(_mapParentObjet.transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int CountSquareNeighbours(int x, int z)
|
||||
{
|
||||
int count = 0;
|
||||
if (x <= 0 || x >= width - 1 || z <= 0 || z >= depth - 1) return 5;
|
||||
if (map[x - 1, z] == 0) count++;
|
||||
if (map[x + 1, z] == 0) count++;
|
||||
if (map[x, z + 1] == 0) count++;
|
||||
if (map[x, z - 1] == 0) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
public int CountDiagonalNeighbours(int x, int z)
|
||||
{
|
||||
int count = 0;
|
||||
if (x <= 0 || x >= width - 1 || z <= 0 || z >= depth - 1) return 5;
|
||||
if (map[x - 1, z - 1] == 0) count++;
|
||||
if (map[x + 1, z + 1] == 0) count++;
|
||||
if (map[x - 1, z + 1] == 0) count++;
|
||||
if (map[x + 1, z - 1] == 0) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
public int CountAllNeighbours(int x, int z)
|
||||
{
|
||||
return CountSquareNeighbours(x,z) + CountDiagonalNeighbours(x,z);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1039d646c358a4bd5ac697b0446a2f7e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
16
Assets/Scripts/GameSetup/Maze/MazeCellType.cs
Normal file
16
Assets/Scripts/GameSetup/Maze/MazeCellType.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace Hallucinate.GameSetup.Maze
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the state of each cell in the maze.
|
||||
/// Used to replace magic numbers and drive visual changes.
|
||||
/// </summary>
|
||||
public enum MazeCellType
|
||||
{
|
||||
Wall, // Solid block
|
||||
Corridor, // Finalized path
|
||||
Processing, // Currently being evaluated by algorithm (Debug)
|
||||
Path, // Temporary path (e.g., Wilson's crawler)
|
||||
Start, // Entry point
|
||||
End // Exit point
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/GameSetup/Maze/MazeCellType.cs.meta
Normal file
2
Assets/Scripts/GameSetup/Maze/MazeCellType.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f54ef08fa4922eb4a968d46c7aa71faf
|
||||
71
Assets/Scripts/GameSetup/Maze/MazeGrid.cs
Normal file
71
Assets/Scripts/GameSetup/Maze/MazeGrid.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Hallucinate.GameSetup.Maze
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds the logical state of the maze grid.
|
||||
/// Notifies listeners whenever a cell changes to trigger visual updates.
|
||||
/// </summary>
|
||||
public class MazeGrid
|
||||
{
|
||||
public int Width { get; }
|
||||
public int Depth { get; }
|
||||
|
||||
private readonly MazeCellType[,] _cells;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when a cell's type is changed.
|
||||
/// Useful for the Renderer to trigger animations/FX.
|
||||
/// </summary>
|
||||
public event Action<int, int, MazeCellType> OnCellChanged;
|
||||
|
||||
public MazeGrid(int width, int depth)
|
||||
{
|
||||
Width = width;
|
||||
Depth = depth;
|
||||
_cells = new MazeCellType[width, depth];
|
||||
|
||||
// Initialize all as walls
|
||||
for (int z = 0; z < depth; z++)
|
||||
for (int x = 0; x < width; x++)
|
||||
_cells[x, z] = MazeCellType.Wall;
|
||||
}
|
||||
|
||||
public void SetCell(int x, int z, MazeCellType type)
|
||||
{
|
||||
if (IsInBounds(x, z))
|
||||
{
|
||||
if (_cells[x, z] != type)
|
||||
{
|
||||
_cells[x, z] = type;
|
||||
OnCellChanged?.Invoke(x, z, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MazeCellType GetCell(int x, int z)
|
||||
{
|
||||
if (IsInBounds(x, z))
|
||||
return _cells[x, z];
|
||||
return MazeCellType.Wall; // Treat out of bounds as walls
|
||||
}
|
||||
|
||||
public bool IsInBounds(int x, int z)
|
||||
{
|
||||
return x >= 0 && x < Width && z >= 0 && z < Depth;
|
||||
}
|
||||
|
||||
public int CountSquareNeighbours(int x, int z, MazeCellType targetType)
|
||||
{
|
||||
int count = 0;
|
||||
if (x <= 0 || x >= Width - 1 || z <= 0 || z >= Depth - 1) return 5;
|
||||
|
||||
if (GetCell(x - 1, z) == targetType) count++;
|
||||
if (GetCell(x + 1, z) == targetType) count++;
|
||||
if (GetCell(x, z + 1) == targetType) count++;
|
||||
if (GetCell(x, z - 1) == targetType) count++;
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/GameSetup/Maze/MazeGrid.cs.meta
Normal file
2
Assets/Scripts/GameSetup/Maze/MazeGrid.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1a7a252ff0b1014a9690f08897e2e59
|
||||
81
Assets/Scripts/GameSetup/Maze/MazeManager.cs
Normal file
81
Assets/Scripts/GameSetup/Maze/MazeManager.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Hallucinate.GameSetup.Maze
|
||||
{
|
||||
/// <summary>
|
||||
/// Central controller for the Maze system.
|
||||
/// Manages algorithm selection, debug speed, and regeneration.
|
||||
/// </summary>
|
||||
public class MazeManager : MonoBehaviour
|
||||
{
|
||||
public enum AlgorithmType { Recursive, Wilsons, Prims, Crawler }
|
||||
|
||||
[Header("System Settings")]
|
||||
[SerializeField] private AlgorithmType selectedAlgorithm;
|
||||
[SerializeField] private int width = 30;
|
||||
[SerializeField] private int depth = 30;
|
||||
|
||||
[Header("Debug Settings")]
|
||||
[SerializeField] private bool debugMode = true;
|
||||
[Range(0.001f, 0.5f)]
|
||||
[SerializeField] private float visualizationInterval = 0.05f;
|
||||
|
||||
[Header("References")]
|
||||
[SerializeField] private MazeRenderer mazeRenderer;
|
||||
[SerializeField] private Transform mazeContainer;
|
||||
|
||||
private MazeGrid _grid;
|
||||
private Coroutine _generationCoroutine;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Regenerate();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.R))
|
||||
{
|
||||
Regenerate();
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Regenerate")]
|
||||
public void Regenerate()
|
||||
{
|
||||
if (_generationCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_generationCoroutine);
|
||||
}
|
||||
|
||||
mazeRenderer.Clear();
|
||||
_grid = new MazeGrid(width, depth);
|
||||
mazeRenderer.Initialize(_grid, mazeContainer);
|
||||
|
||||
IMazeAlgorithm algorithm = GetAlgorithm(selectedAlgorithm);
|
||||
|
||||
if (debugMode)
|
||||
{
|
||||
_generationCoroutine = StartCoroutine(algorithm.GenerateStepByStep(_grid, visualizationInterval));
|
||||
}
|
||||
else
|
||||
{
|
||||
algorithm.Generate(_grid);
|
||||
}
|
||||
}
|
||||
|
||||
private IMazeAlgorithm GetAlgorithm(AlgorithmType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
AlgorithmType.Recursive => new RecursiveAlgorithm(),
|
||||
AlgorithmType.Wilsons => new WilsonsAlgorithm(),
|
||||
AlgorithmType.Prims => new PrimsAlgorithm(),
|
||||
AlgorithmType.Crawler => new CrawlerAlgorithm(),
|
||||
_ => new RecursiveAlgorithm()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/GameSetup/Maze/MazeManager.cs.meta
Normal file
2
Assets/Scripts/GameSetup/Maze/MazeManager.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3607adabe0c29c34591af73b414eb17a
|
||||
104
Assets/Scripts/GameSetup/Maze/MazeRenderer.cs
Normal file
104
Assets/Scripts/GameSetup/Maze/MazeRenderer.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Hallucinate.GameSetup.Maze
|
||||
{
|
||||
/// <summary>
|
||||
/// Responsible for the visual representation of the maze.
|
||||
/// Handles spawning, pooling, and animations with safety checks.
|
||||
/// </summary>
|
||||
public class MazeRenderer : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private MazeVisualProfile visualProfile;
|
||||
|
||||
private readonly Dictionary<Vector2Int, GameObject> _spawnedCells = new Dictionary<Vector2Int, GameObject>();
|
||||
private Transform _container;
|
||||
|
||||
public void Initialize(MazeGrid grid, Transform container)
|
||||
{
|
||||
_container = container;
|
||||
grid.OnCellChanged += HandleCellChanged;
|
||||
|
||||
// Initial render
|
||||
for (int z = 0; z < grid.Depth; z++)
|
||||
{
|
||||
for (int x = 0; x < grid.Width; x++)
|
||||
{
|
||||
UpdateCellVisual(x, z, grid.GetCell(x, z), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
StopAllCoroutines();
|
||||
|
||||
foreach (var cell in _spawnedCells.Values)
|
||||
{
|
||||
if (cell != null) Destroy(cell);
|
||||
}
|
||||
_spawnedCells.Clear();
|
||||
}
|
||||
|
||||
private void HandleCellChanged(int x, int z, MazeCellType type)
|
||||
{
|
||||
UpdateCellVisual(x, z, type, true);
|
||||
}
|
||||
|
||||
private void UpdateCellVisual(int x, int z, MazeCellType type, bool animate)
|
||||
{
|
||||
Vector2Int pos = new Vector2Int(x, z);
|
||||
|
||||
if (_spawnedCells.TryGetValue(pos, out GameObject oldObj))
|
||||
{
|
||||
Destroy(oldObj);
|
||||
_spawnedCells.Remove(pos);
|
||||
}
|
||||
|
||||
GameObject prefab = visualProfile.GetPrefab(type);
|
||||
if (prefab == null) return;
|
||||
|
||||
// Ensure scale is always positive to avoid BoxCollider issues
|
||||
float safeScale = Mathf.Max(0.001f, visualProfile.scale);
|
||||
Vector3 worldPos = new Vector3(x * safeScale, 0, z * safeScale);
|
||||
|
||||
GameObject newObj = Instantiate(prefab, worldPos, Quaternion.identity, _container);
|
||||
newObj.transform.localScale = Vector3.one * safeScale;
|
||||
_spawnedCells[pos] = newObj;
|
||||
|
||||
if (animate && visualProfile.animationDuration > 0)
|
||||
{
|
||||
StartCoroutine(AnimateCell(newObj.transform));
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator AnimateCell(Transform target)
|
||||
{
|
||||
if (target == null) yield break;
|
||||
|
||||
float duration = Mathf.Max(0.01f, visualProfile.animationDuration);
|
||||
float elapsed = 0;
|
||||
Vector3 finalScale = target.localScale;
|
||||
target.localScale = Vector3.one * 0.001f; // Use tiny positive instead of zero
|
||||
|
||||
while (elapsed < duration)
|
||||
{
|
||||
if (target == null) yield break;
|
||||
|
||||
elapsed += Time.deltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / duration);
|
||||
float s = Mathf.Sin(t * Mathf.PI * 0.5f);
|
||||
|
||||
// Ensure s is never negative
|
||||
target.localScale = finalScale * Mathf.Max(0.001f, s);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
target.localScale = finalScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/GameSetup/Maze/MazeRenderer.cs.meta
Normal file
2
Assets/Scripts/GameSetup/Maze/MazeRenderer.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f30df611110713742ab984f5bead5d88
|
||||
34
Assets/Scripts/GameSetup/Maze/MazeVisualProfile.cs
Normal file
34
Assets/Scripts/GameSetup/Maze/MazeVisualProfile.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Hallucinate.GameSetup.Maze
|
||||
{
|
||||
[CreateAssetMenu(fileName = "MazeVisualProfile", menuName = "Hallucinate/Maze/Visual Profile")]
|
||||
public class MazeVisualProfile : ScriptableObject
|
||||
{
|
||||
[Header("Prefabs")]
|
||||
public GameObject wallPrefab;
|
||||
public GameObject corridorPrefab;
|
||||
public GameObject processingPrefab;
|
||||
public GameObject pathPrefab;
|
||||
public GameObject startPrefab;
|
||||
public GameObject endPrefab;
|
||||
|
||||
[Header("Visualization Settings")]
|
||||
public float scale = 1f;
|
||||
public float animationDuration = 0.25f;
|
||||
|
||||
public GameObject GetPrefab(MazeCellType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
MazeCellType.Wall => wallPrefab,
|
||||
MazeCellType.Corridor => corridorPrefab,
|
||||
MazeCellType.Processing => processingPrefab,
|
||||
MazeCellType.Path => pathPrefab,
|
||||
MazeCellType.Start => startPrefab,
|
||||
MazeCellType.End => endPrefab,
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/GameSetup/Maze/MazeVisualProfile.cs.meta
Normal file
2
Assets/Scripts/GameSetup/Maze/MazeVisualProfile.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3ff96571406a624381b7b0e596a4d1b
|
||||
@@ -1,39 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class Prims : Maze
|
||||
{
|
||||
public override void Generate()
|
||||
{
|
||||
int x = 2;
|
||||
int z = 2;
|
||||
|
||||
map[x, z] = 0;
|
||||
|
||||
List<MapLocation> walls = new List<MapLocation>();
|
||||
walls.Add(new MapLocation(x + 1, z));
|
||||
walls.Add(new MapLocation(x - 1, z));
|
||||
walls.Add(new MapLocation(x, z + 1));
|
||||
walls.Add(new MapLocation(x, z - 1));
|
||||
|
||||
int countloops = 0;
|
||||
while (walls.Count > 0 && countloops < 5000)
|
||||
{
|
||||
int rwall = Random.Range(0, walls.Count);
|
||||
x = walls[rwall].x;
|
||||
z = walls[rwall].z;
|
||||
walls.RemoveAt(rwall);
|
||||
if (CountSquareNeighbours(x, z) == 1)
|
||||
{
|
||||
map[x, z] = 0;
|
||||
walls.Add(new MapLocation(x + 1, z));
|
||||
walls.Add(new MapLocation(x - 1, z));
|
||||
walls.Add(new MapLocation(x, z + 1));
|
||||
walls.Add(new MapLocation(x, z - 1));
|
||||
}
|
||||
|
||||
countloops++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f12a5f6746a454e08a295f64a34f5dcf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
106
Assets/Scripts/GameSetup/Maze/PrimsAlgorithm.cs
Normal file
106
Assets/Scripts/GameSetup/Maze/PrimsAlgorithm.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Hallucinate.GameSetup.Maze
|
||||
{
|
||||
public class PrimsAlgorithm : IMazeAlgorithm
|
||||
{
|
||||
private const int InitialX = 2;
|
||||
private const int InitialZ = 2;
|
||||
private const int MaxIterations = 10000;
|
||||
private const int TargetCorridorNeighbours = 1;
|
||||
|
||||
public void Generate(MazeGrid grid)
|
||||
{
|
||||
int x = InitialX;
|
||||
int z = InitialZ;
|
||||
grid.SetCell(x, z, MazeCellType.Corridor);
|
||||
|
||||
List<MapLocation> walls = GetNeighbouringWalls(grid, x, z);
|
||||
|
||||
int iterations = 0;
|
||||
while (walls.Count > 0 && iterations < MaxIterations)
|
||||
{
|
||||
int rIndex = Random.Range(0, walls.Count);
|
||||
MapLocation w = walls[rIndex];
|
||||
walls.RemoveAt(rIndex);
|
||||
|
||||
if (grid.CountSquareNeighbours(w.x, w.z, MazeCellType.Corridor) == TargetCorridorNeighbours)
|
||||
{
|
||||
grid.SetCell(w.x, w.z, MazeCellType.Corridor);
|
||||
|
||||
foreach (var nw in GetNeighbouringWalls(grid, w.x, w.z))
|
||||
{
|
||||
if (!walls.Contains(nw)) walls.Add(nw);
|
||||
}
|
||||
}
|
||||
iterations++;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator GenerateStepByStep(MazeGrid grid, float interval)
|
||||
{
|
||||
int x = InitialX;
|
||||
int z = InitialZ;
|
||||
grid.SetCell(x, z, MazeCellType.Corridor);
|
||||
yield return new WaitForSeconds(interval);
|
||||
|
||||
List<MapLocation> walls = GetNeighbouringWalls(grid, x, z);
|
||||
foreach(var w in walls) grid.SetCell(w.x, w.z, MazeCellType.Processing);
|
||||
|
||||
int iterations = 0;
|
||||
while (walls.Count > 0 && iterations < MaxIterations)
|
||||
{
|
||||
int rIndex = Random.Range(0, walls.Count);
|
||||
MapLocation w = walls[rIndex];
|
||||
walls.RemoveAt(rIndex);
|
||||
|
||||
if (grid.CountSquareNeighbours(w.x, w.z, MazeCellType.Corridor) == TargetCorridorNeighbours)
|
||||
{
|
||||
grid.SetCell(w.x, w.z, MazeCellType.Corridor);
|
||||
if (interval > 0) yield return new WaitForSeconds(interval);
|
||||
|
||||
foreach (var nw in GetNeighbouringWalls(grid, w.x, w.z))
|
||||
{
|
||||
if (grid.GetCell(nw.x, nw.z) == MazeCellType.Wall)
|
||||
{
|
||||
grid.SetCell(nw.x, nw.z, MazeCellType.Processing);
|
||||
walls.Add(nw);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it's no longer a candidate, turn it back to Wall
|
||||
grid.SetCell(w.x, w.z, MazeCellType.Wall);
|
||||
}
|
||||
iterations++;
|
||||
}
|
||||
}
|
||||
|
||||
private List<MapLocation> GetNeighbouringWalls(MazeGrid grid, int x, int z)
|
||||
{
|
||||
List<MapLocation> neighbours = new List<MapLocation>();
|
||||
foreach (var dir in MapLocation.Directions)
|
||||
{
|
||||
int nx = x + dir.x;
|
||||
int nz = z + dir.z;
|
||||
|
||||
// Correction
|
||||
nx = x + dir.x;
|
||||
nz = z + dir.z;
|
||||
|
||||
if (grid.IsInBounds(nx, nz))
|
||||
{
|
||||
MazeCellType type = grid.GetCell(nx, nz);
|
||||
if (type == MazeCellType.Wall || type == MazeCellType.Processing)
|
||||
{
|
||||
neighbours.Add(new MapLocation(nx, nz));
|
||||
}
|
||||
}
|
||||
}
|
||||
return neighbours;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/GameSetup/Maze/PrimsAlgorithm.cs.meta
Normal file
2
Assets/Scripts/GameSetup/Maze/PrimsAlgorithm.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: edcdd3c0aa9656a4797b83cc675aa629
|
||||
@@ -1,25 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class Recursive : Maze
|
||||
{
|
||||
public override void Generate()
|
||||
{
|
||||
Generate(5, 5);
|
||||
}
|
||||
|
||||
void Generate(int x, int z)
|
||||
{
|
||||
if (CountSquareNeighbours(x, z) >= 2) return;
|
||||
map[x, z] = 0;
|
||||
|
||||
directions.Shuffle();
|
||||
|
||||
Generate(x + directions[0].x, z + directions[0].z);
|
||||
Generate(x + directions[1].x, z + directions[1].z);
|
||||
Generate(x + directions[2].x, z + directions[2].z);
|
||||
Generate(x + directions[3].x, z + directions[3].z);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33bbdb95ccc4b4577a62495732a02d3e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
69
Assets/Scripts/GameSetup/Maze/RecursiveAlgorithm.cs
Normal file
69
Assets/Scripts/GameSetup/Maze/RecursiveAlgorithm.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Hallucinate.GameSetup.Maze.Extensions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Hallucinate.GameSetup.Maze
|
||||
{
|
||||
public class RecursiveAlgorithm : IMazeAlgorithm
|
||||
{
|
||||
private const int StartX = 5;
|
||||
private const int StartZ = 5;
|
||||
private const int DeadEndNeighbourThreshold = 2;
|
||||
|
||||
private readonly List<MapLocation> _directions = MapLocation.Directions;
|
||||
|
||||
public void Generate(MazeGrid grid)
|
||||
{
|
||||
GenerateRecursive(grid, StartX, StartZ);
|
||||
}
|
||||
|
||||
public IEnumerator GenerateStepByStep(MazeGrid grid, float interval)
|
||||
{
|
||||
yield return GenerateRecursiveStepByStep(grid, StartX, StartZ, interval);
|
||||
}
|
||||
|
||||
private void GenerateRecursive(MazeGrid grid, int x, int z)
|
||||
{
|
||||
if (grid.CountSquareNeighbours(x, z, MazeCellType.Corridor) >= DeadEndNeighbourThreshold) return;
|
||||
|
||||
grid.SetCell(x, z, MazeCellType.Corridor);
|
||||
|
||||
List<MapLocation> shuffledDirs = new List<MapLocation>(_directions);
|
||||
shuffledDirs.Shuffle();
|
||||
|
||||
foreach (var dir in shuffledDirs)
|
||||
{
|
||||
int nx = x + dir.x;
|
||||
int nz = z + dir.z;
|
||||
if (grid.IsInBounds(nx, nz))
|
||||
{
|
||||
GenerateRecursive(grid, nx, nz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator GenerateRecursiveStepByStep(MazeGrid grid, int x, int z, float interval)
|
||||
{
|
||||
if (grid.CountSquareNeighbours(x, z, MazeCellType.Corridor) >= DeadEndNeighbourThreshold) yield break;
|
||||
|
||||
grid.SetCell(x, z, MazeCellType.Processing);
|
||||
if (interval > 0) yield return new WaitForSeconds(interval);
|
||||
|
||||
grid.SetCell(x, z, MazeCellType.Corridor);
|
||||
|
||||
List<MapLocation> shuffledDirs = new List<MapLocation>(_directions);
|
||||
shuffledDirs.Shuffle();
|
||||
|
||||
foreach (var dir in shuffledDirs)
|
||||
{
|
||||
int nx = x + dir.x;
|
||||
int nz = z + dir.z;
|
||||
if (grid.IsInBounds(nx, nz))
|
||||
{
|
||||
yield return GenerateRecursiveStepByStep(grid, nx, nz, interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/GameSetup/Maze/RecursiveAlgorithm.cs.meta
Normal file
2
Assets/Scripts/GameSetup/Maze/RecursiveAlgorithm.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2460c0e9379da9741b3d3387aa6c7a8e
|
||||
@@ -1,108 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class Wilsons : Maze
|
||||
{
|
||||
|
||||
List<MapLocation> notUsed = new List<MapLocation>();
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
//create a starting cell
|
||||
int x = Random.Range(2, width - 1);
|
||||
int z = Random.Range(2, depth - 1);
|
||||
map[x, z] = 2;
|
||||
|
||||
while(GetAvailableCells() > 1)
|
||||
RandomWalk();
|
||||
}
|
||||
|
||||
int CountSquareMazeNeighbours(int x, int z)
|
||||
{
|
||||
int count = 0;
|
||||
for (int d = 0; d < directions.Count; d++)
|
||||
{
|
||||
int nx = x + directions[d].x;
|
||||
int nz = z + directions[d].z;
|
||||
if (map[nx, nz] == 2)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int GetAvailableCells()
|
||||
{
|
||||
notUsed.Clear();
|
||||
for (int z = 1; z < depth - 1; z++)
|
||||
for (int x = 1; x < width - 1; x++)
|
||||
{
|
||||
if (CountSquareMazeNeighbours(x, z) == 0)
|
||||
{
|
||||
notUsed.Add(new MapLocation(x, z));
|
||||
}
|
||||
}
|
||||
|
||||
return notUsed.Count;
|
||||
}
|
||||
|
||||
void RandomWalk()
|
||||
{
|
||||
List<MapLocation> inWalk = new List<MapLocation>();
|
||||
int cx;
|
||||
int cz;
|
||||
int rstartIndex = Random.Range(0, notUsed.Count);
|
||||
|
||||
cx = notUsed[rstartIndex].x;
|
||||
cz = notUsed[rstartIndex].z;
|
||||
|
||||
inWalk.Add(new MapLocation(cx, cz));
|
||||
|
||||
int loop = 0;
|
||||
bool validPath = false;
|
||||
while (cx > 0 && cx < width - 1 && cz > 0 && cz < depth - 1 && loop < 5000 && !validPath)
|
||||
{
|
||||
map[cx, cz] = 0;
|
||||
if (CountSquareMazeNeighbours(cx, cz) > 1)
|
||||
break;
|
||||
|
||||
int rd = Random.Range(0, directions.Count);
|
||||
int nx = cx + directions[rd].x;
|
||||
int nz = cz + directions[rd].z;
|
||||
if (CountSquareNeighbours(nx, nz) < 2)
|
||||
{
|
||||
cx = nx;
|
||||
cz = nz;
|
||||
inWalk.Add(new MapLocation(cx, cz));
|
||||
}
|
||||
|
||||
validPath = CountSquareMazeNeighbours(cx, cz) == 1;
|
||||
|
||||
loop++;
|
||||
}
|
||||
|
||||
if (validPath)
|
||||
{
|
||||
map[cx, cz] = 0;
|
||||
Debug.Log("PathFound");
|
||||
|
||||
foreach (MapLocation m in inWalk)
|
||||
{
|
||||
map[m.x, m.z] = 2;
|
||||
}
|
||||
inWalk.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (MapLocation m in inWalk)
|
||||
map[m.x, m.z] = 1;
|
||||
|
||||
inWalk.Clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 502e6aa24e7de43dfb6d20ecd0745176
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
176
Assets/Scripts/GameSetup/Maze/WilsonsAlgorithm.cs
Normal file
176
Assets/Scripts/GameSetup/Maze/WilsonsAlgorithm.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Hallucinate.GameSetup.Maze
|
||||
{
|
||||
/// <summary>
|
||||
/// Wilson's Algorithm implementation based on the original provided logic.
|
||||
/// Ensures paths are sparse and correctly finalized using specific neighbor constraints.
|
||||
/// </summary>
|
||||
public class WilsonsAlgorithm : IMazeAlgorithm
|
||||
{
|
||||
private const int MinBoundary = 2;
|
||||
private const int MaxIterationSafety = 5000;
|
||||
private const int MaxWalkSteps = 5000;
|
||||
|
||||
private readonly List<MapLocation> _directions = MapLocation.Directions;
|
||||
private List<MapLocation> _notUsed = new List<MapLocation>();
|
||||
|
||||
public void Generate(MazeGrid grid)
|
||||
{
|
||||
// 1. Create a starting finalized cell (Type.Corridor represents state 2)
|
||||
int x = Random.Range(MinBoundary, grid.Width - 1);
|
||||
int z = Random.Range(MinBoundary, grid.Depth - 1);
|
||||
grid.SetCell(x, z, MazeCellType.Corridor);
|
||||
|
||||
int safety = 0;
|
||||
while (GetAvailableCells(grid) > 1 && safety < MaxIterationSafety)
|
||||
{
|
||||
RandomWalkSync(grid);
|
||||
safety++;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator GenerateStepByStep(MazeGrid grid, float interval)
|
||||
{
|
||||
int x = Random.Range(MinBoundary, grid.Width - 1);
|
||||
int z = Random.Range(MinBoundary, grid.Depth - 1);
|
||||
grid.SetCell(x, z, MazeCellType.Corridor);
|
||||
yield return new WaitForSeconds(interval);
|
||||
|
||||
int safety = 0;
|
||||
while (GetAvailableCells(grid) > 1 && safety < MaxIterationSafety)
|
||||
{
|
||||
yield return RandomWalk(grid, interval);
|
||||
safety++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Counts neighbors that are already part of the finalized maze (State 2 / Corridor).
|
||||
/// </summary>
|
||||
private int CountFinalizedNeighbours(MazeGrid grid, int x, int z)
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var d in _directions)
|
||||
{
|
||||
if (grid.GetCell(x + d.x, z + d.z) == MazeCellType.Corridor)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private int GetAvailableCells(MazeGrid grid)
|
||||
{
|
||||
_notUsed.Clear();
|
||||
for (int z = 1; z < grid.Depth - 1; z++)
|
||||
{
|
||||
for (int x = 1; x < grid.Width - 1; x++)
|
||||
{
|
||||
if (CountFinalizedNeighbours(grid, x, z) == 0)
|
||||
{
|
||||
_notUsed.Add(new MapLocation(x, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
return _notUsed.Count;
|
||||
}
|
||||
|
||||
private void RandomWalkSync(MazeGrid grid)
|
||||
{
|
||||
if (_notUsed.Count == 0) return;
|
||||
|
||||
List<MapLocation> inWalk = new List<MapLocation>();
|
||||
int rStartIndex = Random.Range(0, _notUsed.Count);
|
||||
int cx = _notUsed[rStartIndex].x;
|
||||
int cz = _notUsed[rStartIndex].z;
|
||||
|
||||
inWalk.Add(new MapLocation(cx, cz));
|
||||
|
||||
int loop = 0;
|
||||
bool validPath = false;
|
||||
while (cx > 0 && cx < grid.Width - 1 && cz > 0 && cz < grid.Depth - 1 && loop < MaxWalkSteps && !validPath)
|
||||
{
|
||||
// Mark as temporary walk (State 0 / Processing)
|
||||
// Note: We don't set grid cell here in sync mode to avoid triggering events unnecessarily
|
||||
// but we keep track of neighbors.
|
||||
|
||||
if (CountFinalizedNeighbours(grid, cx, cz) > 1) break;
|
||||
|
||||
MapLocation rd = _directions[Random.Range(0, _directions.Count)];
|
||||
int nx = cx + rd.x;
|
||||
int nz = cz + rd.z;
|
||||
|
||||
// User's original constraint: CountSquareNeighbours (nx, nz) < 2
|
||||
if (CountFinalizedNeighbours(grid, nx, nz) < 2)
|
||||
{
|
||||
cx = nx;
|
||||
cz = nz;
|
||||
inWalk.Add(new MapLocation(cx, cz));
|
||||
}
|
||||
|
||||
validPath = CountFinalizedNeighbours(grid, cx, cz) == 1;
|
||||
loop++;
|
||||
}
|
||||
|
||||
if (validPath)
|
||||
{
|
||||
foreach (MapLocation m in inWalk)
|
||||
grid.SetCell(m.x, m.z, MazeCellType.Corridor);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator RandomWalk(MazeGrid grid, float interval)
|
||||
{
|
||||
if (_notUsed.Count == 0) yield break;
|
||||
|
||||
List<MapLocation> inWalk = new List<MapLocation>();
|
||||
int rStartIndex = Random.Range(0, _notUsed.Count);
|
||||
int cx = _notUsed[rStartIndex].x;
|
||||
int cz = _notUsed[rStartIndex].z;
|
||||
|
||||
inWalk.Add(new MapLocation(cx, cz));
|
||||
|
||||
int loop = 0;
|
||||
bool validPath = false;
|
||||
while (cx > 0 && cx < grid.Width - 1 && cz > 0 && cz < grid.Depth - 1 && loop < MaxWalkSteps && !validPath)
|
||||
{
|
||||
grid.SetCell(cx, cz, MazeCellType.Processing); // State 0
|
||||
if (interval > 0) yield return new WaitForSeconds(interval);
|
||||
|
||||
if (CountFinalizedNeighbours(grid, cx, cz) > 1) break;
|
||||
|
||||
MapLocation rd = _directions[Random.Range(0, _directions.Count)];
|
||||
int nx = cx + rd.x;
|
||||
int nz = cz + rd.z;
|
||||
|
||||
if (CountFinalizedNeighbours(grid, nx, nz) < 2)
|
||||
{
|
||||
cx = nx;
|
||||
cz = nz;
|
||||
inWalk.Add(new MapLocation(cx, cz));
|
||||
}
|
||||
|
||||
validPath = CountFinalizedNeighbours(grid, cx, cz) == 1;
|
||||
loop++;
|
||||
}
|
||||
|
||||
if (validPath)
|
||||
{
|
||||
foreach (MapLocation m in inWalk)
|
||||
{
|
||||
grid.SetCell(m.x, m.z, MazeCellType.Corridor); // State 2
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (MapLocation m in inWalk)
|
||||
grid.SetCell(m.x, m.z, MazeCellType.Wall); // State 1
|
||||
}
|
||||
inWalk.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/GameSetup/Maze/WilsonsAlgorithm.cs.meta
Normal file
2
Assets/Scripts/GameSetup/Maze/WilsonsAlgorithm.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61156f8986612ca49a0672ad5542380f
|
||||
Reference in New Issue
Block a user