/// <summary> /// This is a helper method for the pathfnding that searches the grid positions adjacent to the current node to determine if the node is in the grid (using the try/catch) /// and that the open/closed lists do not already contain the node (as this would create an infinite loop) /// </summary> /// <returns>List<Node> l_returnNodes (A list of nodes adjacent to the current node)</returns> /// <param name="l_openList">The pathfinding algorithm's open list</param> /// <param name="l_closedList">The pathfinding algorithm's closed list</param> /// <param name="l_currentNode">The node to find adjecant nodes to</param> protected List <Node> FindNeighbours(List <Node> l_openList, List <Node> l_closedList, Node l_currentNode) { int[] l_startGrid = GridTest.GetArrayPosFromVector(l_currentNode.c_nodePosition); //Debug.Log (l_startGrid[0] + ", " + l_startGrid[1] + " is grid pos, current node transform = " + l_currentNode.c_nodePosition); List <Node> l_returnNodes = new List <Node>(); Node l_tempNode = new Node(new Vector3(0, 0, 0)); try{ l_tempNode = GridTest.s_gridPosArray [l_startGrid [0] + 1, l_startGrid [1]]; if (!ListContains(l_openList, l_tempNode) && !ListContains(l_closedList, l_tempNode)) { l_returnNodes.Add(l_tempNode); } } catch { } try{ l_tempNode = GridTest.s_gridPosArray [l_startGrid [0] - 1, l_startGrid [1]]; if (!ListContains(l_openList, l_tempNode) && !ListContains(l_closedList, l_tempNode)) { l_returnNodes.Add(l_tempNode); } } catch { } try{ l_tempNode = GridTest.s_gridPosArray [l_startGrid [0], l_startGrid [1] + 1]; if (!ListContains(l_openList, l_tempNode) && !ListContains(l_closedList, l_tempNode)) { l_returnNodes.Add(l_tempNode); } } catch { } try{ l_tempNode = GridTest.s_gridPosArray [l_startGrid [0], l_startGrid [1] - 1]; if (!ListContains(l_openList, l_tempNode) && !ListContains(l_closedList, l_tempNode)) { l_returnNodes.Add(l_tempNode); } } catch { } return(l_returnNodes); }
/// <summary> /// Uses an A* algorithm to find the shortest path to the node the player selected. /// </summary> /// <returns>The path.</returns> /// <param name="l_startPos">The player's start position.</param> /// <param name="l_endPos">The node the player is trying to reach.</param> private Vector3[] CalculatePath(Vector3 l_startPos, Vector3 l_endPos) { List <Node> l_openList = new List <Node>(); List <Node> l_closedList = new List <Node>(); int[] l_tempGrid = GridTest.GetArrayPosFromVector(l_endPos); Node l_endNode = GridTest.s_gridPosArray [l_tempGrid[0], l_tempGrid[1]]; Vector3[] l_returnArray = new Vector3[0]; bool l_foundPath = false; l_tempGrid = GridTest.GetArrayPosFromVector(l_startPos); Node l_startNode = GridTest.s_gridPosArray [l_tempGrid[0], l_tempGrid[1]]; l_openList.Add(l_startNode); while (l_openList.Count > 0) { Node l_nextNode = new Node(new Vector3(0, 0, 0)); l_nextNode.c_gCost = 5000; l_nextNode.c_fCost = 5000; for (int n = 0; n < l_openList.Count; n++) { if (l_openList[n].c_fCost < l_nextNode.c_fCost) { l_nextNode = l_openList[n]; } } l_openList.Remove(l_nextNode); l_closedList.Add(l_nextNode); if (l_nextNode.c_nodePosition == l_endPos) { l_foundPath = true; l_endNode = l_nextNode; Debug.Log("Found path, breaking"); Debug.Log("Node parent = " + l_endNode.c_parentNode.c_nodePosition); break; } List <Node> l_neighbourNodes = FindNeighbours(l_openList, l_closedList, l_nextNode); for (int n = 0; n < l_neighbourNodes.Count; n++) { if (IsThereObstruction(l_neighbourNodes[n].c_nodePosition) || ListContains(l_closedList, l_neighbourNodes[n])) { continue; } if (l_neighbourNodes[n].c_parentNode == null) { l_neighbourNodes[n].c_parentNode = l_nextNode; } if (l_neighbourNodes[n].c_gCost > l_neighbourNodes[n].c_parentNode.c_gCost + 1 || !ListContains(l_openList, l_neighbourNodes[n])) { l_neighbourNodes[n].c_gCost = l_neighbourNodes[n].c_parentNode.c_gCost++; l_neighbourNodes[n].c_hCost = Mathf.Abs(l_neighbourNodes[n].c_nodePosition.x - l_endPos.x) + Mathf.Abs(l_neighbourNodes[n].c_nodePosition.z - l_endPos.z); l_neighbourNodes[n].c_fCost = l_neighbourNodes[n].c_gCost + l_neighbourNodes[n].c_hCost; l_neighbourNodes[n].c_parentNode = l_nextNode; Debug.Log("Setting Node parent"); if (!ListContains(l_openList, l_neighbourNodes[n])) { l_openList.Add(l_neighbourNodes[n]); } } } } if (l_foundPath) { Debug.Log("Found path, calling backtrack"); l_returnArray = CalculateBacktrack(l_startNode, l_endNode); } for (int n = 0; n < l_closedList.Count; n++) { l_closedList [n].c_gCost = 0; l_closedList [n].c_fCost = 0; l_closedList [n].c_parentNode = null; } for (int n = 0; n < l_openList.Count; n++) { l_openList [n].c_gCost = 0; l_openList [n].c_fCost = 0; l_openList [n].c_parentNode = null; } return(l_returnArray); }
/// <summary> /// This method uses a Dijkstra algoritm to create a list of all floor tiles within the argument's range. /// I have used for loops as opposed to foreach loops for efficiency and created my own List.Contains() /// method that loops through the list to find a comparable node as this too is much more efficient. /// </summary> /// <returns>GameObject[] l_returnArea: List of game objects in range of the player.</returns> /// <param name="l_startPos">: Player's position in the world (Vector3).</param> /// <param name="l_range">: Range that player can move (int).</param> private GameObject[] CalculateArea(Vector3 l_startPos, int l_range) { List <Node> l_areaInRange = new List <Node>(); List <Node> l_openList = new List <Node>(); List <Node> l_closedList = new List <Node>(); int[] l_tempGrid; l_tempGrid = GridTest.GetArrayPosFromVector(l_startPos); Node l_startNode = GridTest.s_gridPosArray [l_tempGrid[0], l_tempGrid[1]]; l_openList.Add(l_startNode); while (l_openList.Count > 0) { Node l_nextNode = new Node(new Vector3(0, 0, 0)); l_nextNode.c_gCost = int.MaxValue; for (int n = 0; n < l_openList.Count; n++) { if (l_openList[n].c_gCost < l_nextNode.c_gCost) { l_nextNode = l_openList[n]; } } if (l_nextNode == null) { break; } l_openList.Remove(l_nextNode); l_closedList.Add(l_nextNode); if (l_nextNode.c_gCost > l_range) { continue; } List <Node> l_neighbourNodes = FindNeighbours(l_openList, l_closedList, l_nextNode); for (int n = 0; n < l_neighbourNodes.Count; n++) { if (IsThereObstruction(l_neighbourNodes[n].c_nodePosition) || ListContains(l_closedList, l_neighbourNodes[n])) { continue; } if (l_neighbourNodes[n].c_parentNode == null || !ListContains(l_closedList, l_neighbourNodes[n].c_parentNode)) { l_neighbourNodes[n].c_parentNode = l_nextNode; } if ((l_neighbourNodes[n].c_gCost > (l_neighbourNodes[n].c_parentNode.c_gCost + 1) || l_neighbourNodes[n].c_gCost == 0) || !ListContains(l_openList, l_neighbourNodes[n])) { l_neighbourNodes[n].c_gCost = l_neighbourNodes[n].c_parentNode.c_gCost + 1; l_neighbourNodes[n].c_fCost = l_neighbourNodes[n].c_gCost; l_neighbourNodes[n].c_parentNode = l_nextNode; if (!ListContains(l_openList, l_neighbourNodes[n]) && l_neighbourNodes[n].c_gCost <= l_range) { l_openList.Add(l_neighbourNodes[n]); Debug.Log("GCost = " + l_neighbourNodes [n].c_gCost + " added to openList"); if (!ListContains(l_areaInRange, l_neighbourNodes[n])) { l_areaInRange.Add(l_neighbourNodes[n]); Debug.Log("GCost = " + l_neighbourNodes [n].c_gCost + " added to areaInRangeList"); } } } } } List <GameObject> l_returnArea = new List <GameObject> (); foreach (Node n in l_areaInRange) { Debug.Log(n.c_nodePosition); } for (int n = 0; n < l_areaInRange.Count; n++) { l_areaInRange [n].c_gCost = 0; l_areaInRange [n].c_fCost = 0; l_areaInRange [n].c_parentNode = null; GameObject l_tempObj = GridTest.GetTileFromVector(l_areaInRange[n].c_nodePosition); if (l_tempObj != null) { l_returnArea.Add(l_tempObj); } } return(l_returnArea.ToArray()); }