mirror of
https://github.com/Xevion/Paths.git
synced 2025-12-14 12:12:23 -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_PrefabInstance: {fileID: 0}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 519420028}
|
m_GameObject: {fileID: 519420028}
|
||||||
m_Enabled: 1
|
m_Enabled: 0
|
||||||
--- !u!20 &519420031
|
--- !u!20 &519420031
|
||||||
Camera:
|
Camera:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -575,7 +575,7 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
gridMaterial: {fileID: 2100000, guid: 780d53bea4df7b0418e9c8ed8afd6410, type: 2}
|
gridMaterial: {fileID: 2100000, guid: 780d53bea4df7b0418e9c8ed8afd6410, type: 2}
|
||||||
size: 31
|
size: 32
|
||||||
--- !u!23 &2092623186
|
--- !u!23 &2092623186
|
||||||
MeshRenderer:
|
MeshRenderer:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@@ -11,11 +11,8 @@ namespace Algorithms {
|
|||||||
private List<Node> _closedList;
|
private List<Node> _closedList;
|
||||||
private List<GridState> _states;
|
private List<GridState> _states;
|
||||||
|
|
||||||
private Vector2Int _start;
|
public Vector2Int Start { get; private set; }
|
||||||
private Vector2Int _end;
|
public Vector2Int End { get; private set; }
|
||||||
|
|
||||||
public Vector2Int Start { get => _start; }
|
|
||||||
public Vector2Int End { get => _end; }
|
|
||||||
|
|
||||||
public AStar(NodeGrid nodeGrid) {
|
public AStar(NodeGrid nodeGrid) {
|
||||||
this._nodeGrid = nodeGrid;
|
this._nodeGrid = nodeGrid;
|
||||||
@@ -23,8 +20,8 @@ namespace Algorithms {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Stack<Node> FindPath(Vector2Int start, Vector2Int end) {
|
public Stack<Node> FindPath(Vector2Int start, Vector2Int end) {
|
||||||
this._start = start;
|
this.Start = start;
|
||||||
this._end = end;
|
this.End = end;
|
||||||
|
|
||||||
var startNode = new Node(start, true);
|
var startNode = new Node(start, true);
|
||||||
var endNode = new Node(end, true);
|
var endNode = new Node(end, true);
|
||||||
@@ -58,16 +55,16 @@ namespace Algorithms {
|
|||||||
|
|
||||||
_openList.Add(n);
|
_openList.Add(n);
|
||||||
_openList = _openList.OrderBy(node => node.F).ToList();
|
_openList = _openList.OrderBy(node => node.F).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RecordState();
|
RecordState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct path, if end was not closed return null
|
// 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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +86,7 @@ namespace Algorithms {
|
|||||||
public void RecordState() {
|
public void RecordState() {
|
||||||
// TODO: Record pathfinding state information (stages, heuristic, statistical info)
|
// TODO: Record pathfinding state information (stages, heuristic, statistical info)
|
||||||
this._states.Add(
|
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
|
// Fill grid with width*height nodes, zero-indexed
|
||||||
foreach (int x in Enumerable.Range(0, width - 1)) {
|
foreach (int x in Enumerable.Range(0, width - 1)) {
|
||||||
List<Node> list = new List<Node>(height);
|
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));
|
list.Add(new Node(new Vector2Int(x, y), true));
|
||||||
|
|
||||||
grid.Add(list);
|
grid.Add(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
Width = width;
|
Width = this.grid.Count;
|
||||||
Height = height;
|
Height = this.grid[0].Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodeGrid(List<List<Node>> grid) {
|
public NodeGrid(List<List<Node>> grid) {
|
||||||
@@ -42,8 +42,8 @@ namespace Algorithms {
|
|||||||
public List<Node> GetAdjacentNodes(Node node) {
|
public List<Node> GetAdjacentNodes(Node node) {
|
||||||
List<Node> temp = new List<Node>();
|
List<Node> temp = new List<Node>();
|
||||||
|
|
||||||
int row = node.Position.y;
|
|
||||||
int col = node.Position.x;
|
int col = node.Position.x;
|
||||||
|
int row = node.Position.y;
|
||||||
|
|
||||||
if (row + 1 < Height) temp.Add(grid[col][row + 1]);
|
if (row + 1 < Height) temp.Add(grid[col][row + 1]);
|
||||||
if (row - 1 >= 0) 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];
|
return grid[x][y];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FlipRandomWall() {
|
public Node GetNode(Vector2Int position) {
|
||||||
grid[Random.Range(0, Width - 1)][Random.Range(0, Height - 1)].Walkable = false;
|
return GetNode(position.x, position.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float Manhattan(Node first, Node second) {
|
/// <summary>
|
||||||
return Math.Abs(first.Position.x - second.Position.x) + Math.Abs(first.Position.y - second.Position.y);
|
/// 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) {
|
public static float Manhattan(Node a, Node b) {
|
||||||
return Manhattan(new Node(algorithmStart, false), new Node(algorithmEnd, false));
|
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>
|
/// <summary>
|
||||||
|
|||||||
@@ -66,9 +66,11 @@ public class GridController : MonoBehaviour {
|
|||||||
/// <param name="gridState"></param>
|
/// <param name="gridState"></param>
|
||||||
public void LoadGridState(GridState gridState) {
|
public void LoadGridState(GridState gridState) {
|
||||||
// Loop over matrix and set values via cast Enum to int
|
// Loop over matrix and set values via cast Enum to int
|
||||||
foreach(int x in Enumerable.Range(0, gridState.Grid.Count - 1))
|
for (int x = 0; x < gridState.Grid.GetLength(0); x++) {
|
||||||
foreach(int y in Enumerable.Range(0, gridState.Grid[0].Count - 1))
|
for (int y = 0; y < gridState.Grid.GetLength(1); y++)
|
||||||
this.SetValue(x, y, (int) gridState.Grid[x][y]);
|
this.SetValue(x, y, (int) gridState.Grid[x, y]);
|
||||||
|
}
|
||||||
|
|
||||||
UpdateShader(PropertyName.Values);
|
UpdateShader(PropertyName.Values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,55 +1,58 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Algorithms;
|
using Algorithms;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class GridState {
|
public class GridState {
|
||||||
public List<List<GridNodeType>> Grid;
|
public readonly GridNodeType[,] Grid;
|
||||||
|
|
||||||
|
// public List<List<GridNodeType>> Grid;
|
||||||
public float time;
|
public float time;
|
||||||
|
|
||||||
public GridState(NodeGrid grid, IEnumerable<Node> seen, IEnumerable<Node> expanded, Vector2Int start,
|
public GridState(NodeGrid grid, IEnumerable<Node> seen, IEnumerable<Node> expanded, Vector2Int start,
|
||||||
Vector2Int end, IReadOnlyCollection<Node> path) {
|
Vector2Int end, IReadOnlyCollection<Node> path) {
|
||||||
time = Time.realtimeSinceStartup;
|
time = Time.realtimeSinceStartup;
|
||||||
Grid = new List<List<GridNodeType>>(grid.Width);
|
|
||||||
|
Grid = new GridNodeType[grid.Width, grid.Height];
|
||||||
|
|
||||||
// Add walls and empty tiles
|
// Add walls and empty tiles
|
||||||
foreach (var x in Enumerable.Range(0, grid.Width - 1)) {
|
for (int x = 0; x < grid.Width; x++) {
|
||||||
Grid.Add(new List<GridNodeType>(grid.Height));
|
for (int y = 0; y < grid.Height; y++) {
|
||||||
foreach (var y in Enumerable.Range(0, grid.Height - 1)) {
|
|
||||||
Node node = grid.GetNode(x, 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
|
// Add 'seen' tiles
|
||||||
foreach (Node seenNode in seen)
|
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
|
// Add 'expanded' tiles
|
||||||
foreach (Node expandedNode in expanded)
|
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
|
// Add 'path' tiles
|
||||||
if (path != null)
|
if (path != null)
|
||||||
foreach (Node pathNode in path)
|
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
|
// Set start and end tiles
|
||||||
Grid[start.x][start.y] = GridNodeType.Start;
|
Grid[start.x, start.y] = GridNodeType.Start;
|
||||||
Grid[end.x][end.y] = GridNodeType.End;
|
Grid[end.x, end.y] = GridNodeType.End;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<GridNodeType> GetNodes() {
|
// public IEnumerable<GridNodeType> GetNodes() {
|
||||||
return Grid.SelectMany(nodeList => nodeList).ToList();
|
// return Grid.SelectMany(nodeList => nodeList).ToList();
|
||||||
}
|
// }
|
||||||
|
|
||||||
public string RenderGrid() {
|
// public string RenderGrid() {
|
||||||
string result = "";
|
// string result = "";
|
||||||
foreach (List<GridNodeType> nodeTypes in Grid) {
|
// foreach (List<GridNodeType> nodeTypes in Grid) {
|
||||||
result = nodeTypes.Aggregate(result, (current, nodeType) => current + $"{(int) nodeType}") + "\n";
|
// 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() {
|
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() {
|
public void Update() {
|
||||||
@@ -49,9 +50,13 @@ public class Manager : MonoBehaviour {
|
|||||||
Vector2Int start = new Vector2Int(30, 30);
|
Vector2Int start = new Vector2Int(30, 30);
|
||||||
Vector2Int end = nodeGrid.RandomPosition();
|
Vector2Int end = nodeGrid.RandomPosition();
|
||||||
|
|
||||||
int wallCount = (int) (gridController.size * gridController.size * 0.5);
|
|
||||||
foreach (int unused in Enumerable.Range(0, wallCount))
|
int wallCount = (int) (gridController.size * gridController.size * 0.25);
|
||||||
nodeGrid.FlipRandomWall();
|
for (int unused = 0; unused < wallCount; unused++)
|
||||||
|
nodeGrid.AddRandomWall();
|
||||||
|
|
||||||
|
nodeGrid.GetNode(start).Walkable = true;
|
||||||
|
nodeGrid.GetNode(end).Walkable = true;
|
||||||
|
|
||||||
path = _algorithm.FindPath(start, end);
|
path = _algorithm.FindPath(start, end);
|
||||||
|
|
||||||
@@ -64,7 +69,8 @@ public class Manager : MonoBehaviour {
|
|||||||
|
|
||||||
float change = state.time - lastStart;
|
float change = state.time - lastStart;
|
||||||
string pathCount = path != null ? $"{path.Count}" : "N/A";
|
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";
|
debugText.text =
|
||||||
_curIndex += 1;
|
$"{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