void OpenNode(AStarWithMinBinaryHeapNode currentNode, Vector2 direction) { AStarWithMinBinaryHeapNode newNode = GetNode(currentNode, direction); if (newNode == null || !newNode.canThrough) { return; //如果没获取到新节点或新节点不能通行则直接return } switch (newNode.state) { case AStarWithMinBinaryNodeState.unopened: DoOpenNode(currentNode, newNode); break; case AStarWithMinBinaryNodeState.opened: if (currentNode.startToCost < newNode.nextNode.startToCost) //如果新节点已经开了但从起点到指向的节点的成本比当前节点高 { ReopenNode(currentNode, newNode); } break; case AStarWithMinBinaryNodeState.closed: break; } }
string GetDirectionText(AStarWithMinBinaryHeapNode node) { if (node == null || node.nextNode == null) { return(""); } Vector2 direction = node.nextNode.position - node.position; if (direction == Vector2.up) { return("↑"); } if (direction == Vector2.right) { return("→"); } if (direction == Vector2.down) { return("↓"); } if (direction == Vector2.left) { return("←"); } return(""); }
void OpenStartNode() { AStarWithMinBinaryHeapNode startNode = GetNode(_startPosition); startNode.Open(_endPosition); _openedList.Set(startNode); }
public void Reset() //寻路开始时清空成本和指向 { _state = AStarWithMinBinaryNodeState.unopened; _nextNode = null; _startToCost = 0; _toEndCost = 0; _totalCost = 0; }
public void Pathfind_CantFind() { AStarWithMinBinary aStar = new AStarWithMinBinary(7, 7); Vector2 startPosition = new Vector2(0, 0); Vector2 endPosition = new Vector2(6, 6); aStar.SetObstacle(new Vector2(0, 1)); aStar.SetObstacle(new Vector2(1, 1)); aStar.SetObstacle(new Vector2(2, 1)); aStar.SetObstacle(new Vector2(4, 1)); aStar.SetObstacle(new Vector2(4, 2)); aStar.SetObstacle(new Vector2(4, 3)); aStar.SetObstacle(new Vector2(5, 3)); aStar.SetObstacle(new Vector2(6, 3)); aStar.SetObstacle(new Vector2(1, 4)); aStar.SetObstacle(new Vector2(2, 4)); aStar.SetObstacle(new Vector2(3, 4)); aStar.SetObstacle(new Vector2(2, 5)); aStar.SetObstacle(new Vector2(0, 6)); aStar.SetObstacle(new Vector2(1, 6)); aStar.FindPath(startPosition, endPosition); /* * N N 0 0 0 0 E * * ↓ ← N 0 0 0 0 * * ↓ N N N 0 0 0 * * → → → ↓ N N N * * → → → ↓ N ↓ ← * * N N N ↓ N ↓ ← * * S ← ← ← ← ← ← */ AStarWithMinBinaryHeapNode[,] matrix = aStar.matrix; AStarWithMinBinaryHeapNode[,] nextNodes = new AStarWithMinBinaryHeapNode[7, 7] { { null, matrix[0, 0], matrix[1, 0], matrix[2, 0], matrix[3, 0], matrix[4, 0], matrix[5, 0] }, { null, null, null, matrix[3, 0], null, matrix[5, 0], matrix[5, 1] }, { matrix[1, 2], matrix[2, 2], matrix[3, 2], matrix[3, 1], null, matrix[5, 1], matrix[5, 2] }, { matrix[1, 3], matrix[2, 3], matrix[3, 3], matrix[3, 2], null, null, null }, { matrix[0, 3], null, null, null, null, null, null }, { matrix[0, 4], matrix[0, 5], null, null, null, null, null }, { null, null, null, null, null, null, null } }; for (int x = 0; x < 7; x++) { for (int y = 0; y < 7; y++) { Assert.AreEqual(nextNodes[y, x], aStar.matrix[x, y].nextNode); //横y竖x,何等反人类,而且竟然严格符合了数组下标顺序:前面是第一层,后面是第二层 } } }
public void Remove(AStarWithMinBinaryHeapNode node) { var targetSubHeap = _heap.FindFirstThroughValue(node.totalCost); targetSubHeap.RemoveFirstThroughObj(node); if (targetSubHeap.Count == 0) { _heap.RemoveFirstThroughObj(targetSubHeap); } }
Color GetNodeColor(AStarWithMinBinaryHeapNode node, float maxStartToCost, float maxToEndCost) { if (!node.canThrough) { return(Color.black); } Color nodeRed = Color.red * node.startToCost / maxStartToCost; Color nodeBlue = Color.blue * node.toEndCost / maxToEndCost; return(nodeRed + nodeBlue + Color.gray * 0.5f); }
public void Set(AStarWithMinBinaryHeapNode node) { MinBinaryHeap <AStarWithMinBinaryHeapNode> subHeap = _heap.FindFirstThroughValue(node.totalCost); if (subHeap != null) { subHeap.SetNode(node, node.toEndCost); } else { subHeap = new MinBinaryHeap <AStarWithMinBinaryHeapNode>(); subHeap.SetNode(node, node.toEndCost); _heap.SetNode(subHeap, node.totalCost); } }
void DisplayPath() { AStarWithMinBinaryHeapNode currentNode = _aStar.GetNode(_endPosition); if (currentNode == null || currentNode.nextNode == null) { return; } while (currentNode.nextNode != null) { AddGreen(currentNode); currentNode = currentNode.nextNode; } AddGreen(currentNode); }
public void Pathfind_CanFind_NoObstacle() { AStarWithMinBinary aStar = new AStarWithMinBinary(7, 7); Vector2 startPosition = new Vector2(0, 0); Vector2 endPosition = new Vector2(6, 6); aStar.FindPath(startPosition, endPosition); /* * ↓ ← ← ← ← ← E * * ↓ ← ↑ ↑ ↑ ↑ 0 * * ↓ ← 0 0 0 0 0 * * ↓ ← 0 0 0 0 0 * * ↓ ← 0 0 0 0 0 * * ↓ ← 0 0 0 0 0 * * S ← 0 0 0 0 0 */ AStarWithMinBinaryHeapNode[,] matrix = aStar.matrix; AStarWithMinBinaryHeapNode[,] nextNodes = new AStarWithMinBinaryHeapNode[7, 7] { { null, matrix[0, 0], null, null, null, null, null }, { matrix[0, 0], matrix[0, 1], null, null, null, null, null }, { matrix[0, 1], matrix[0, 2], null, null, null, null, null }, { matrix[0, 2], matrix[0, 3], null, null, null, null, null }, { matrix[0, 3], matrix[0, 4], null, null, null, null, null }, { matrix[0, 4], matrix[0, 5], matrix[2, 6], matrix[3, 6], matrix[4, 6], matrix[5, 6], null }, { matrix[0, 5], matrix[0, 6], matrix[1, 6], matrix[2, 6], matrix[3, 6], matrix[4, 6], matrix[5, 6] } }; for (int x = 0; x < 7; x++) { for (int y = 0; y < 7; y++) { Assert.AreEqual(nextNodes[y, x], aStar.matrix[x, y].nextNode); //二维数组赋值是按照横竖x的方式进行的,也就是说上面的矩阵写错了,要转置,这就是一个用 [y, x] 一个用 [x, y] 的原因 } } }
public AStarWithMinBinary(int width, int height) { if (width < 0) { width = 0; //防止传入负数 } if (height < 0) { height = 0; //防止传入负数 } _matrix = new AStarWithMinBinaryHeapNode[width, height]; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { _matrix[x, y] = new AStarWithMinBinaryHeapNode(x, y); } } }
private void DoFindPath() { OpenStartNode(); while (!_openedList.isEmpty) { AStarWithMinBinaryHeapNode currentNode = _openedList.GetMinimumCostNode(); if (IsDestination(currentNode)) { break; } OpenNode(currentNode, Vector2.up); OpenNode(currentNode, Vector2.right); OpenNode(currentNode, Vector2.down); OpenNode(currentNode, Vector2.left); CloseNode(currentNode); } }
void MouseMiddleDown() { Vector2 position = GetMousePosition(); AStarWithMinBinaryHeapNode node = _aStar.GetNode(position); if (node == null) { return; } if (node.canThrough) { _aStar.SetObstacle(position); } else { _aStar.RemoveObstacle(position); } DoFindPath(); }
void CloseNode(AStarWithMinBinaryHeapNode node) { _openedList.Remove(node); node.Close(); }
bool IsDestination(AStarWithMinBinaryHeapNode currentNode) { return(currentNode == GetNode(_endPosition)); }
void AddGreen(AStarWithMinBinaryHeapNode currentNode) { Vector2 position = currentNode.position; _displayMatrix[(int)position.x, (int)position.y].GetComponentInChildren <Image>().color += Color.green; }
void DoOpenNode(AStarWithMinBinaryHeapNode currentNode, AStarWithMinBinaryHeapNode openNode) { openNode.Open(currentNode, _endPosition); _openedList.Set(openNode); }
void ReopenNode(AStarWithMinBinaryHeapNode currentNode, AStarWithMinBinaryHeapNode openNode) { _openedList.Remove(openNode); DoOpenNode(currentNode, openNode); }
void DisplayANode(AStarWithMinBinaryHeapNode node, GameObject displayer, float maxStartToCost, float maxToEndCost) { displayer.GetComponentInChildren <Image>().color = GetNodeColor(node, maxStartToCost, maxToEndCost); displayer.GetComponentInChildren <Text>().text = GetDirectionText(node); }
public AStarWithMinBinaryHeapNode GetNode(AStarWithMinBinaryHeapNode node, Vector2 direction) { return(GetNode(node.position + direction)); }
public void Open(AStarWithMinBinaryHeapNode nextNode, Vector2 destination) { _state = AStarWithMinBinaryNodeState.opened; _nextNode = nextNode; ComputeCost(destination); }