Exemple #1
0
    /* A* Psuedo code:
     *
     * Open set of nodes to be evaluated
     * Closed set of nodes that have already been evaluated
     *
     * loop
     *  current = node in the open set with the lowest fCost
     *  remove curent node from the open set
     *  add the current node to the closed set
     *
     * if the current node is the target node
     *  return <-- this is where the target node has been found
     *
     * foreach neighbor of the current node
     *  if neighbor is not traversable or neighbor is in the closed set
     *      skip to the next neighbor
     *
     *  if the new path to the neighbor is shorter or the neighbor is not in the open set
     *      set the fCost of the neighbor
     *      set the parent of the neighbor to the current node
     *      if the neighbor node is not in the open set
     *          add the neighbor to the open set
     */

    // initiate the A* pathfinder co-routine
    IEnumerator FindPath(Vector3 startPos, Vector3 targetPos)
    {
        Vector3[] waypoints   = new Vector3[0];
        bool      pathSuccess = false;

        // get the node locations for the starting position and the target position
        Node startNode  = grid.NodeFromWorldPoint(startPos);
        Node targetNode = grid.NodeFromWorldPoint(targetPos);

        //print("X: " + startPos.x + ", Y: " + startPos.y);
        //print("[" + targetNode.gridX + ", " + targetNode.gridY + "]");

        playerNode = targetNode;

        // setup the sets of open and closed nodes
        //List<Node> openGridPoints = new List<Node>();
        Heap <Node>    openGridPoints   = new Heap <Node>(grid.MaxSize);
        HashSet <Node> closedGridPoints = new HashSet <Node>();

        // add the current node to the open set
        openGridPoints.AddNewT(startNode);

        // start the loop
        while (openGridPoints.Count > 0)
        {
            // set the current node to the first item in the open set
            Node currentNode = openGridPoints.RemoveFirst();
            closedGridPoints.Add(currentNode);

            // if the current node is the target node, the path is complete
            // retrace the path and exit out of the algorithm
            if (currentNode == targetNode)
            {
                pathSuccess = true;
                break;
            }

            // checking all of the neighbors of the current node
            foreach (Node neighbor in grid.GetNeighbors(currentNode))
            {
                // if the neighbor is not usable, skip it
                if (!neighbor.walkable || closedGridPoints.Contains(neighbor))
                {
                    continue;
                }

                // set up the new movement cost to the neighbor
                int newMovementCostToNeighbor = currentNode.gCost + GetDistance(currentNode, neighbor);

                // if the distance is shorter to the neighbor, or the neighbor is not in the open set
                if (newMovementCostToNeighbor < neighbor.gCost || !openGridPoints.Contains(neighbor))
                {
                    // set the fCost of the neighbor
                    neighbor.gCost = newMovementCostToNeighbor;
                    neighbor.hCost = GetDistance(neighbor, targetNode);

                    // make parent of the neighbor the current node
                    neighbor.parent = currentNode;

                    // if the neighbor is not a part of the open set, add it
                    if (!openGridPoints.Contains(neighbor))
                    {
                        openGridPoints.AddNewT(neighbor);
                    }
                    else
                    {
                        openGridPoints.UpdateItem(neighbor);
                    }
                }
            }
        }

        yield return(null);

        if (pathSuccess)
        {
            waypoints = RetracePath(startNode, targetNode); // set up the waypoints to the path
        }

        requestManager.FinishedProcessingPath(waypoints, pathSuccess); // send the success over to the manager
    }