mirror of
https://github.com/Xevion/Paths.git
synced 2025-12-10 14:08:01 -06:00
switched GridState operations from List to 2d array, attempting to fix off-by-one mistakes, fix unwalkable start after nodeGrid.AddRandomWall
This commit is contained in:
@@ -145,7 +145,7 @@ AudioListener:
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 519420028}
|
||||
m_Enabled: 1
|
||||
m_Enabled: 0
|
||||
--- !u!20 &519420031
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -575,7 +575,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
gridMaterial: {fileID: 2100000, guid: 780d53bea4df7b0418e9c8ed8afd6410, type: 2}
|
||||
size: 31
|
||||
size: 32
|
||||
--- !u!23 &2092623186
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -11,11 +11,8 @@ namespace Algorithms {
|
||||
private List<Node> _closedList;
|
||||
private List<GridState> _states;
|
||||
|
||||
private Vector2Int _start;
|
||||
private Vector2Int _end;
|
||||
|
||||
public Vector2Int Start { get => _start; }
|
||||
public Vector2Int End { get => _end; }
|
||||
public Vector2Int Start { get; private set; }
|
||||
public Vector2Int End { get; private set; }
|
||||
|
||||
public AStar(NodeGrid nodeGrid) {
|
||||
this._nodeGrid = nodeGrid;
|
||||
@@ -23,17 +20,17 @@ namespace Algorithms {
|
||||
}
|
||||
|
||||
public Stack<Node> FindPath(Vector2Int start, Vector2Int end) {
|
||||
this._start = start;
|
||||
this._end = end;
|
||||
this.Start = start;
|
||||
this.End = end;
|
||||
|
||||
var startNode = new Node(start, true);
|
||||
var endNode = new Node(end, true);
|
||||
|
||||
|
||||
|
||||
_path = new Stack<Node>();
|
||||
_openList = new List<Node>();
|
||||
_closedList = new List<Node>();
|
||||
|
||||
|
||||
RecordState();
|
||||
Node current = startNode;
|
||||
|
||||
@@ -58,16 +55,16 @@ namespace Algorithms {
|
||||
|
||||
_openList.Add(n);
|
||||
_openList = _openList.OrderBy(node => node.F).ToList();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RecordState();
|
||||
}
|
||||
}
|
||||
|
||||
// construct path, if end was not closed return null
|
||||
if (!_closedList.Exists(x => x.Position == endNode.Position)) {
|
||||
if (!_closedList.Exists(node => node.Position == endNode.Position)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -89,7 +86,7 @@ namespace Algorithms {
|
||||
public void RecordState() {
|
||||
// TODO: Record pathfinding state information (stages, heuristic, statistical info)
|
||||
this._states.Add(
|
||||
new GridState(this._nodeGrid, this._openList, this._closedList, _start, _end, _path)
|
||||
new GridState(this._nodeGrid, this._openList, this._closedList, Start, End, _path)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,14 +22,14 @@ namespace Algorithms {
|
||||
// Fill grid with width*height nodes, zero-indexed
|
||||
foreach (int x in Enumerable.Range(0, width - 1)) {
|
||||
List<Node> list = new List<Node>(height);
|
||||
foreach (int y in Enumerable.Range(0, height))
|
||||
foreach (int y in Enumerable.Range(0, height - 1))
|
||||
list.Add(new Node(new Vector2Int(x, y), true));
|
||||
|
||||
grid.Add(list);
|
||||
}
|
||||
|
||||
Width = width;
|
||||
Height = height;
|
||||
Width = this.grid.Count;
|
||||
Height = this.grid[0].Count;
|
||||
}
|
||||
|
||||
public NodeGrid(List<List<Node>> grid) {
|
||||
@@ -42,8 +42,8 @@ namespace Algorithms {
|
||||
public List<Node> GetAdjacentNodes(Node node) {
|
||||
List<Node> temp = new List<Node>();
|
||||
|
||||
int row = node.Position.y;
|
||||
int col = node.Position.x;
|
||||
int row = node.Position.y;
|
||||
|
||||
if (row + 1 < Height) temp.Add(grid[col][row + 1]);
|
||||
if (row - 1 >= 0) temp.Add(grid[col][row - 1]);
|
||||
@@ -71,16 +71,31 @@ namespace Algorithms {
|
||||
return grid[x][y];
|
||||
}
|
||||
|
||||
public void FlipRandomWall() {
|
||||
grid[Random.Range(0, Width - 1)][Random.Range(0, Height - 1)].Walkable = false;
|
||||
public Node GetNode(Vector2Int position) {
|
||||
return GetNode(position.x, position.y);
|
||||
}
|
||||
|
||||
public static float Manhattan(Node first, Node second) {
|
||||
return Math.Abs(first.Position.x - second.Position.x) + Math.Abs(first.Position.y - second.Position.y);
|
||||
/// <summary>
|
||||
/// Finds one random walkable cell and turns it into a wall.
|
||||
/// </summary>
|
||||
public void AddRandomWall() {
|
||||
while (true) {
|
||||
int x = Random.Range(0, Width - 1);
|
||||
int y = Random.Range(0, Height - 1);
|
||||
|
||||
if (grid[x][y].Walkable) {
|
||||
grid[x][y].Walkable = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static float Manhattan(Vector2Int algorithmStart, Vector2Int algorithmEnd) {
|
||||
return Manhattan(new Node(algorithmStart, false), new Node(algorithmEnd, false));
|
||||
public static float Manhattan(Node a, Node b) {
|
||||
return Math.Abs(a.Position.x - b.Position.x) + Math.Abs(a.Position.y - b.Position.y);
|
||||
}
|
||||
|
||||
public static float Manhattan(Vector2Int a, Vector2Int b) {
|
||||
return Manhattan(new Node(a, false), new Node(b, false));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -14,7 +14,7 @@ public enum PropertyName {
|
||||
public class GridController : MonoBehaviour {
|
||||
public Material gridMaterial; // Maintain reference to the Grid Material the Shader is implanted upon
|
||||
public int size = 32; // Size of the grid, width and height
|
||||
|
||||
|
||||
// Value management
|
||||
private int[] _values;
|
||||
private ComputeBuffer _buffer;
|
||||
@@ -54,7 +54,7 @@ public class GridController : MonoBehaviour {
|
||||
throw new ArgumentOutOfRangeException(nameof(property), property, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnApplicationQuit() {
|
||||
// Release ComputeBuffer memory
|
||||
_buffer.Release();
|
||||
@@ -66,12 +66,14 @@ public class GridController : MonoBehaviour {
|
||||
/// <param name="gridState"></param>
|
||||
public void LoadGridState(GridState gridState) {
|
||||
// Loop over matrix and set values via cast Enum to int
|
||||
foreach(int x in Enumerable.Range(0, gridState.Grid.Count - 1))
|
||||
foreach(int y in Enumerable.Range(0, gridState.Grid[0].Count - 1))
|
||||
this.SetValue(x, y, (int) gridState.Grid[x][y]);
|
||||
for (int x = 0; x < gridState.Grid.GetLength(0); x++) {
|
||||
for (int y = 0; y < gridState.Grid.GetLength(1); y++)
|
||||
this.SetValue(x, y, (int) gridState.Grid[x, y]);
|
||||
}
|
||||
|
||||
UpdateShader(PropertyName.Values);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets a value in the 1D array at a particular 2D coordinate
|
||||
/// </summary>
|
||||
@@ -81,7 +83,7 @@ public class GridController : MonoBehaviour {
|
||||
public void SetValue(int x, int y, int value) {
|
||||
_values[size * y + x] = value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the value at a 2D coordinate within the 1D array
|
||||
/// </summary>
|
||||
|
||||
@@ -1,55 +1,58 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Algorithms;
|
||||
using UnityEngine;
|
||||
|
||||
public class GridState {
|
||||
public List<List<GridNodeType>> Grid;
|
||||
public readonly GridNodeType[,] Grid;
|
||||
|
||||
// public List<List<GridNodeType>> Grid;
|
||||
public float time;
|
||||
|
||||
public GridState(NodeGrid grid, IEnumerable<Node> seen, IEnumerable<Node> expanded, Vector2Int start,
|
||||
Vector2Int end, IReadOnlyCollection<Node> path) {
|
||||
time = Time.realtimeSinceStartup;
|
||||
Grid = new List<List<GridNodeType>>(grid.Width);
|
||||
|
||||
Grid = new GridNodeType[grid.Width, grid.Height];
|
||||
|
||||
// Add walls and empty tiles
|
||||
foreach (var x in Enumerable.Range(0, grid.Width - 1)) {
|
||||
Grid.Add(new List<GridNodeType>(grid.Height));
|
||||
foreach (var y in Enumerable.Range(0, grid.Height - 1)) {
|
||||
for (int x = 0; x < grid.Width; x++) {
|
||||
for (int y = 0; y < grid.Height; y++) {
|
||||
Node node = grid.GetNode(x, y);
|
||||
Grid[x].Add(!node.Walkable ? GridNodeType.Wall : GridNodeType.Empty);
|
||||
Grid[x, y] = node.Walkable ? GridNodeType.Empty : GridNodeType.Wall;
|
||||
}
|
||||
}
|
||||
|
||||
// Add 'seen' tiles
|
||||
foreach (Node seenNode in seen)
|
||||
Grid[seenNode.Position.x][seenNode.Position.y] = GridNodeType.Seen;
|
||||
Grid[seenNode.Position.x, seenNode.Position.y] = GridNodeType.Seen;
|
||||
|
||||
// Add 'expanded' tiles
|
||||
foreach (Node expandedNode in expanded)
|
||||
Grid[expandedNode.Position.x][expandedNode.Position.y] = GridNodeType.Expanded;
|
||||
Grid[expandedNode.Position.x, expandedNode.Position.y] = GridNodeType.Expanded;
|
||||
|
||||
|
||||
// Add 'path' tiles
|
||||
if (path != null)
|
||||
foreach (Node pathNode in path)
|
||||
Grid[pathNode.Position.y][pathNode.Position.y] = GridNodeType.Path;
|
||||
Grid[pathNode.Position.x, pathNode.Position.y] = GridNodeType.Path;
|
||||
|
||||
// Set start and end tiles
|
||||
Grid[start.x][start.y] = GridNodeType.Start;
|
||||
Grid[end.x][end.y] = GridNodeType.End;
|
||||
Grid[start.x, start.y] = GridNodeType.Start;
|
||||
Grid[end.x, end.y] = GridNodeType.End;
|
||||
}
|
||||
|
||||
public IEnumerable<GridNodeType> GetNodes() {
|
||||
return Grid.SelectMany(nodeList => nodeList).ToList();
|
||||
}
|
||||
// public IEnumerable<GridNodeType> GetNodes() {
|
||||
// return Grid.SelectMany(nodeList => nodeList).ToList();
|
||||
// }
|
||||
|
||||
public string RenderGrid() {
|
||||
string result = "";
|
||||
foreach (List<GridNodeType> nodeTypes in Grid) {
|
||||
result = nodeTypes.Aggregate(result, (current, nodeType) => current + $"{(int) nodeType}") + "\n";
|
||||
}
|
||||
// public string RenderGrid() {
|
||||
// string result = "";
|
||||
// foreach (List<GridNodeType> nodeTypes in Grid) {
|
||||
// result = nodeTypes.Aggregate(result, (current, nodeType) => current + $"{(int) nodeType}") + "\n";
|
||||
// }
|
||||
|
||||
return result;
|
||||
}
|
||||
// return result;
|
||||
// }
|
||||
}
|
||||
@@ -23,7 +23,8 @@ public class Manager : MonoBehaviour {
|
||||
}
|
||||
|
||||
public void OnDrawGizmos() {
|
||||
Gizmos.DrawSphere(transform.position, 1);
|
||||
float size = (float) (10.0 / gridController.size);
|
||||
Gizmos.DrawWireCube(transform.position, new Vector3(size, size, size));
|
||||
}
|
||||
|
||||
public void Update() {
|
||||
@@ -48,10 +49,14 @@ public class Manager : MonoBehaviour {
|
||||
// Vector2 start = nodeGrid.RandomPosition();
|
||||
Vector2Int start = new Vector2Int(30, 30);
|
||||
Vector2Int end = nodeGrid.RandomPosition();
|
||||
|
||||
|
||||
int wallCount = (int) (gridController.size * gridController.size * 0.5);
|
||||
foreach (int unused in Enumerable.Range(0, wallCount))
|
||||
nodeGrid.FlipRandomWall();
|
||||
int wallCount = (int) (gridController.size * gridController.size * 0.25);
|
||||
for (int unused = 0; unused < wallCount; unused++)
|
||||
nodeGrid.AddRandomWall();
|
||||
|
||||
nodeGrid.GetNode(start).Walkable = true;
|
||||
nodeGrid.GetNode(end).Walkable = true;
|
||||
|
||||
path = _algorithm.FindPath(start, end);
|
||||
|
||||
@@ -64,7 +69,8 @@ public class Manager : MonoBehaviour {
|
||||
|
||||
float change = state.time - lastStart;
|
||||
string pathCount = path != null ? $"{path.Count}" : "N/A";
|
||||
debugText.text = $"{change * 1000.0:F1}ms\n{this._curIndex:000} / {this._states.Count:000}\nPath: {pathCount} tiles";
|
||||
_curIndex += 1;
|
||||
debugText.text =
|
||||
$"{change * 1000.0:F1}ms\n{this._curIndex:000} / {this._states.Count:000}\nPath: {pathCount} tiles";
|
||||
_curIndex += 3;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user