fix start/end nodes not being properly handled in algorithm with ChangeController

essentially, the start and end nodes were being marked as Seen and/or Expanded instead of as Start/End nodes. The end node was easy to correct, but the start node was difficult without messing with the algorithm's performance (potentially), so I opted for a dirtier but probably more performant measure by just removing the Change value type.
This commit is contained in:
Xevion
2020-11-24 20:42:38 -06:00
parent e637eac65b
commit bfff8fdb57
4 changed files with 45 additions and 27 deletions
+12 -12
View File
@@ -24,14 +24,12 @@ 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;
ChangeController.AddChange(new Change(start.x, start.y, GridNodeType.Start, GridNodeType.Empty)); ChangeController.AddChange(new Change(start.x, start.y, GridNodeType.Start, GridNodeType.Empty));
ChangeController.AddChange(new Change(end.x, end.y, GridNodeType.End, GridNodeType.Empty)); ChangeController.AddChange(new Change(end.x, end.y, GridNodeType.End, GridNodeType.Empty));
Node startNode = _nodeGrid.Grid[start.x, start.y];
var startNode = new Node(start, true); Node endNode = _nodeGrid.Grid[end.x, end.y];
var endNode = new Node(end, true);
_path = new Stack<Node>(); _path = new Stack<Node>();
_openList = new List<Node>(); _openList = new List<Node>();
@@ -41,23 +39,22 @@ namespace Algorithms {
Node current = startNode; Node current = startNode;
// add start node to Open List // add start node to Open List
startNode.State = NodeState.Open;
_openList.Add(startNode); _openList.Add(startNode);
while (_openList.Count != 0) { while (_openList.Count != 0) {
current = _openList.First(); current = _openList[0];
_openList.Remove(current); _openList.RemoveAt(0);
current.State = NodeState.Closed; current.State = NodeState.Closed;
ChangeController.AddChange(new Change( ChangeController.AddChange(new Change(
current.Position.x, current.Position.y, current.Position.x, current.Position.y,
GridNodeType.Expanded, GridNodeType.Seen)); GridNodeType.Expanded, GridNodeType.Seen));
_closedList.Add(current); _closedList.Add(current);
if (current.Position == endNode.Position) if (current.Position == endNode.Position)
break; break;
RecordState();
Node[] adjacentNodes = this._nodeGrid.GetAdjacentNodesArray(current); Node[] adjacentNodes = this._nodeGrid.GetAdjacentNodesArray(current);
for (int i = 0; i < adjacentNodes.Length; i++) { for (int i = 0; i < adjacentNodes.Length; i++) {
Node node = adjacentNodes[i]; Node node = adjacentNodes[i];
@@ -68,7 +65,8 @@ namespace Algorithms {
node.Cost = node.Weight + node.Parent.Cost; node.Cost = node.Weight + node.Parent.Cost;
node.State = NodeState.Open; node.State = NodeState.Open;
ChangeController.AddChange(new Change(node.Position.x, node.Position.y, GridNodeType.Seen, GridNodeType.Empty)); ChangeController.AddChange(new Change(node.Position.x, node.Position.y, GridNodeType.Seen,
GridNodeType.Empty));
// Insert the new node into the sorted open list in ascending order // Insert the new node into the sorted open list in ascending order
int index = _openList.BinarySearch(node); int index = _openList.BinarySearch(node);
@@ -83,12 +81,14 @@ namespace Algorithms {
return null; return null;
} }
// Fix start position being overriden
ChangeController.RemovePositions(start, 1);
// if all good, return path // if all good, return path
Node temp = _closedList[_closedList.IndexOf(current)]; Node temp = _closedList[_closedList.IndexOf(current)];
if (temp == null) return null; if (temp == null) return null;
do { do {
_path.Push(temp); _path.Push(temp);
RecordState();
temp = temp.Parent; temp = temp.Parent;
} while (temp != null && !temp.Equals(startNode)); } while (temp != null && !temp.Equals(startNode));
+4
View File
@@ -12,4 +12,8 @@
this.Old = oldType; this.Old = oldType;
this.Time = UnityEngine.Time.realtimeSinceStartup; this.Time = UnityEngine.Time.realtimeSinceStartup;
} }
public override string ToString() {
return $"Change({X}, {Y}, {Old} -> {New})";
}
} }
+23 -1
View File
@@ -13,11 +13,12 @@ public class ChangeController {
private readonly List<Change> _changes; private readonly List<Change> _changes;
public int Count => _changes.Count; public int Count => _changes.Count;
public Change CurrentChange => _changes[Index]; public Change CurrentChange => _changes[Index];
public double CurrentRuntime => _changes[Index].Time - _changes[0].Time;
public ChangeController(GridNodeType[,] initial) { public ChangeController(GridNodeType[,] initial) {
_initial = initial; _initial = initial;
Current = initial; Current = initial;
Index = 0; Index = -1;
_changes = new List<Change>(); _changes = new List<Change>();
} }
@@ -104,4 +105,25 @@ public class ChangeController {
else else
Move(diff); Move(diff);
} }
/// <summary>
/// Removes all Change values referencing a specific position.
/// Intended for fixing start and end positions.
/// Works in reverse, i.e. count = 1 removes the last position if any.
/// </summary>
/// <param name="position">The Vector2Int position to look for.</param>
/// <param name="count">Maximum number of Change values to remove. -1 for all.</param>
public void RemovePositions(Vector2Int position, int count = -1) {
if (count == 0)
return;
for (int i = _changes.Count - 1; i >= 0; i--)
if (_changes[i].X == position.x && _changes[i].Y == position.y) {
_changes.RemoveAt(i);
// Return if the count is now zero.
if (--count == 0)
return;
}
}
} }
+6 -14
View File
@@ -13,7 +13,6 @@ public class Manager : MonoBehaviour {
private ChangeController _state; private ChangeController _state;
private int _curIndex; private int _curIndex;
private Stack<Node> _path; private Stack<Node> _path;
private float _lastStart;
private float _runtime; private float _runtime;
public Camera mainCamera; public Camera mainCamera;
@@ -45,16 +44,10 @@ public class Manager : MonoBehaviour {
_runtime += increment; _runtime += increment;
if (CurrentIndex < _state.Count) if (CurrentIndex < _state.Count)
this.LoadNextState(); LoadNextState();
else { else {
try { GeneratePath();
_lastStart = Time.realtimeSinceStartup; CurrentIndex = 0;
GeneratePath();
CurrentIndex = 0;
// _curIndex = path != null && path.Count > 30 ? 0 : _states.Count;
}
catch (ArgumentOutOfRangeException) {
}
} }
} }
@@ -79,9 +72,8 @@ public class Manager : MonoBehaviour {
_state.MoveTo(CurrentIndex); _state.MoveTo(CurrentIndex);
gridController.LoadGridState(_state.Current); gridController.LoadGridState(_state.Current);
float change = _state.CurrentChange.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" + debugText.text = $"{_state.CurrentRuntime * 1000.0:F1}ms\n" +
$"{this.CurrentIndex:000} / {_state.Count:000}\n" + $"{this.CurrentIndex:000} / {_state.Count:000}\n" +
$"Path: {pathCount} tiles"; $"Path: {pathCount} tiles";
} }
@@ -92,11 +84,11 @@ public class Manager : MonoBehaviour {
public void Resize() { public void Resize() {
float ratioImage = (float) gridController.width / gridController.height; float ratioImage = (float) gridController.width / gridController.height;
float ratioScreen = mainCamera.aspect; float ratioScreen = mainCamera.aspect;
var orthographicSize = mainCamera.orthographicSize; var orthographicSize = mainCamera.orthographicSize;
var image = new Vector2(gridController.width, gridController.height); var image = new Vector2(gridController.width, gridController.height);
var screen = new Vector2(2 * orthographicSize * mainCamera.aspect, orthographicSize * 2); var screen = new Vector2(2 * orthographicSize * mainCamera.aspect, orthographicSize * 2);
gridObject.transform.localScale = ratioScreen > ratioImage gridObject.transform.localScale = ratioScreen > ratioImage
? new Vector3(image.x * screen.y / image.y, screen.y, 0.001f) ? new Vector3(image.x * screen.y / image.y, screen.y, 0.001f)
: new Vector3(screen.x, image.y * screen.x / image.x, 0.001f); : new Vector3(screen.x, image.y * screen.x / image.x, 0.001f);