public PathingNode(ITile tile) { this.tile = tile; this.next = null; this.cost = 0f; this.order = 0f; this.isOpen = false; this.isClosed = false; }
public PathingNode CalculatePath() { #region init if (insanityCheck > 5) { this.isEnabled = false; this.isActive = false; return null; } insanityCheck++; List<PathingNode> openList = new List<PathingNode>(); List<PathingNode> nodeList = new List<PathingNode>(); ITile originalTile = Entity.Tile; PathingNode originalNode = new PathingNode(originalTile); // Starting point PathingNode current = new PathingNode(originalTile); current.cost = 0; ITile endTile = this.Destination; if (endTile == originalTile) return current; if (endTile == null) return current; if (endTile is NullTile) return current; #endregion openList.Add(current); while (openList.Count > 0) { current = openList.OrderBy(x => x.cost).First(); // first iteration, only item in openList is the original tile openList.Remove(current); // first iteration, this is now an empty list current.isClosed = true; // first iteration, only node is now closed current.isOpen = false; // first iteration, only node is now not open foreach (ITile tile in current.neighbors) // first iteration, these are the tiles directly adjacent to the entity { PathingNode node = AnalyzeNode(tile, current, originalTile, // first iteration, current is the starting position, tile is an adjacent position - current.tile == originalTile endTile, openList, nodeList); // first iteration, openList and nodeList are empty at this point if (node != null) return node; // node.next.tile is the endTile, originalNode.next should be the first tile } } return current; }
private List<PathingNode> BuildPath(PathingNode node) { List<PathingNode> tempList = new List<PathingNode>(); PathingNode original = node; int order = 0; if (node != null) { order = 1000; // since the original node is the 2nd to last one, we are reversing the order - so count down node.order = order; tempList.Add(node); while (node.next != null) { order -= 1; // noep // since the original node is the 2nd to last one, we are reversing the order - so count down node = node.next; // get next node and store this order number node.order = order; tempList.Add(node); // save in list } } if (tempList.Count > 0) { if (tempList.OrderBy(x => x.order).First().tile != this.Entity.Tile) throw new ArgumentException("Bad list, lowest 'order' should be current location"); else tempList.Remove(tempList.OrderBy(x => x.order).First()); } return tempList; // the original node should have order == 1000, with the path going backwards - lowest number should be the entity's current location }
private PathingNode AnalyzeNode(ITile tile, PathingNode current, ITile originalTile, ITile endTile, List<PathingNode> openList, List<PathingNode> nodeList) { PathingNode node; // node is one of current's neighbors if (tile != null && tile != originalTile) { if (tile.IsBlocked == false //|| tile == endTile ) { // node is one of current's neighbors node = nodeList.Where(x => x.tile == tile).SingleOrDefault(); if (node == null) { // if this is the first time ecountering this tile... node = new PathingNode(tile); // wrap the tile reference in a Node nodeList.Add(node); } if (node.isClosed == false) { #region calculate cost float cost = 0; // higher this is, the worse of a 'guess' it is - it should get smaller as the tiles get closer to the destination // straight line cost += Vector2.Distance(current.tile.Position, endTile.Position); cost += current.cost; // not 100% sure on the logic of this one... #endregion if (cost < node.cost // if the cost just calculated is less than what the node presently has, that means this current node is 'closer' than the selected node || node.cost == 0 // if node.cost is 0, then any other position is a valid guess ) { node.cost = cost; // this is the cost of the new 'next' node (best guess so far), node.next = current; // first.next -> original, second.next -> first, third.next -> second, etc } if (node.isOpen == false) { if (node.tile == endTile) { node.next = current; // node.next is the final location return node; // this is the last node --> goes to BuildPath to assign 'order' values } node.isOpen = true; openList.Add(node); } } } } return null; }