Exemple #1
0
    //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)));
                    }
                }
            }
        }
    }