//Finds the shortest path between two points, if one exists and puts the path into the grid public void FindPath(Vector3 startPos, Vector3 targetPos, int maxLength) { //convert the given positions into pathfinding nodes PathNode startNode = grid.WorldToNode(startPos); PathNode targetNode = grid.WorldToNode(targetPos); //reset gCost of the starting Node startNode.gCost = 0; //sets hCost of starting Node setHCost(startNode, targetNode, true); if (startNode == null) { Debug.Log("Starting Tile Out of Bounds"); return; } else if (targetNode == null) { Debug.Log("Target Tile Out of Bounds"); return; } else if (startNode == targetNode) { Debug.Log("Starting Tile and Target Tile are identical"); return; } //checks if the target tile is farther than the max length of the path else if (startNode.hCost > maxLength) { Debug.Log("Target Tile out of movement range"); return; } //list of pathing nodes that have not been checked yet List <PathNode> OpenList = new List <PathNode>(); //set of pathing nodes that have been checked HashSet <PathNode> ClosedList = new HashSet <PathNode>(); //add the first node to the unchecked nodes OpenList.Add(startNode); //while there are unchecked nodes, keep checking while (OpenList.Count > 0) { //start by looking at the first node PathNode currentNode = OpenList[0]; //comapre to every other node for (int i = 0; i < OpenList.Count; i++) { //if the total cost of a node is lower, or the total cost is equal but node is closer to the target if (OpenList[i].FCost < currentNode.FCost || currentNode.FCost == OpenList[i].FCost && OpenList[i].hCost < currentNode.hCost) { //that node becomes the new current node currentNode = OpenList[i]; } } //remove node from the unchecked nodes OpenList.Remove(currentNode); //add the node to the checked nodes ClosedList.Add(currentNode); //if the current node is the target if (currentNode == targetNode) { startNode.isMoveObstructed = false; targetNode.isMoveObstructed = true; //create a list to contain the final path List <PathNode> finalPath = new List <PathNode>(); //go backwards from the current node until reaching the starting node while (currentNode != startNode) { //add each node to the final path and look at the previous node finalPath.Add(currentNode); currentNode = currentNode.prevNode; } //add the starting node for debug purposes finalPath.Add(currentNode); //reverse the final path so that it goes from start to end, rather than end to start finalPath.Reverse(); //send the final apth to the grid grid.finalPath = finalPath; return; } //look at each adjacent node foreach (PathNode adjacentNode in grid.GetAdjacentNodes(currentNode)) { //if it has already been checked or is obstructed, skip it if (adjacentNode.isMoveObstructed || ClosedList.Contains(adjacentNode)) { continue; } else { //if the adjacent node is more than 1 tile farther from the start than the current node //or if the unchecked nodes list does not contain the adjacent node if (!OpenList.Contains(adjacentNode) || currentNode.gCost + 1 < adjacentNode.gCost) { //the adjacent node's distance from the start node along this path is this node's distance + 1 adjacentNode.gCost = currentNode.gCost + 1; //calculate the adjacent node's distance from the target using manhatten distance //adjacentNode.hCost = Mathf.Abs(adjacentNode.posX - targetNode.posX) + Mathf.Abs(adjacentNode.posY - targetNode.posY); //calculate the adjacent node's distance from the target using pythagorean theorem rounding down setHCost(adjacentNode, targetNode, true); //set the current node as the predecessor of the adjacent node adjacentNode.prevNode = currentNode; //if the unchecked nodes list does not contain the adjacent node and the adjacent node is not too far from the start, add it if (!OpenList.Contains(adjacentNode) && adjacentNode.gCost <= maxLength) { OpenList.Add(adjacentNode); } } } } } return; }
// Update is called once per frame void Update() { //if the player left clicks if (Input.GetMouseButtonDown(0)) { //calculate whether anything has been clicked on Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); RaycastHit2D hit = Physics2D.Raycast(mousePos, Vector2.zero); //if an object containing a formation was clicked on, select it if (hit) { selectedFormation = hit.collider.GetComponent <Formation>(); Debug.Log(selectedFormation.GetName()); } } //if the player right clicks if (Input.GetMouseButtonDown(1)) { //calculate whether anything has been clicked on Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); RaycastHit2D hit = Physics2D.Raycast(mousePos, Vector2.zero); Formation temp = null; if (hit) { temp = hit.collider.GetComponent <Formation>(); //Debug.Log(selectedFormation.GetName()); } //take an action based on the current phase switch (GameController.currentPhase) { case GameController.BattlePhase.MISSILE: if (temp != null) { //add prompt or seperate controls for non-volley missile fire selectedFormation.RangedAttack(temp, true); } break; case GameController.BattlePhase.MOVEMENT: StartCoroutine(selectedFormation.MoveToHex(mousePos)); break; case GameController.BattlePhase.MELEE: if (temp != null) { selectedFormation.MeleeAttack(temp); } break; } } //if hitting enter, change the phase if (Input.GetKeyDown(KeyCode.Return)) { GameController.main.ChangePhase(); } //turn to the right if (Input.GetKeyDown(KeyCode.RightArrow)) { if (selectedFormation != null) { //right arrow key turns the selectedformation to the right selectedFormation.ChangeFacing(1); } } //turn to the left if (Input.GetKeyDown(KeyCode.LeftArrow)) { if (selectedFormation != null) { //right arrow key turns the selectedformation to the right selectedFormation.ChangeFacing(-1); } } //move forward one hex if (Input.GetKeyDown(KeyCode.UpArrow)) { if (selectedFormation != null) { //get the grid and starting node PathGrid grid = selectedFormation.GetPathGrid(); PathNode startNode = grid.WorldToNode(selectedFormation.transform.position); //find the node in front of the formation and move to it foreach (PathNode node in grid.GetAdjacentNodes(startNode)) { if (node.facing == selectedFormation.GetFacing()) { StartCoroutine(selectedFormation.MoveToHex(grid.NodeToWorld(node))); } } } } }