示例#1
0
 private static void ResetNode(AiNode node)
 {
     node.ParentNode    = null;
     node.CurrentCost   = 0;
     node.EstimatedCost = 0;
     node.NodeState     = AiNodeState.Unconsidered;
 }
示例#2
0
        private static List <AiNode> GeneratePath(AiNode endNode)
        {
            List <AiNode> ret     = new List <AiNode>();
            AiNode        current = endNode;

            while (current != null)
            {
                ret.Add(current);
                current = current.ParentNode;
            }

            ret.Reverse();
            return(ret);
        }
示例#3
0
        /// <summary>
        /// Finds the path from the start node to the end node
        /// </summary>
        /// <param name="startPoint">The point to start the search from</param>
        /// <param name="endPoint">The target point to reach</param>
        /// <param name="foundPath">out parameter to indicate if there exists a valid path for the start/end configuration</param>
        /// <returns>Returns a List of Nodes containing the path from start to finish</returns>
        public static List <AiNode> FindPath(AiNode startPoint, AiNode endPoint,
                                             out bool foundPath)
        {
            int iterations      = 0;
            int nodesConsidered = 2;

            Logger.Log(DebugChannel.EngineAI | DebugChannel.Log, $"A* Query Start:{startPoint} {endPoint}", 10);
            Stopwatch sw = Stopwatch.StartNew();

            if (startPoint == endPoint)
            {
                sw.Stop();
                Logger.Log(DebugChannel.EngineAI | DebugChannel.Log, $"A* Iteration Found Path: ", 9);

                WriteStatistics(nodesConsidered, iterations, sw.ElapsedMilliseconds, 0, 0);

                foundPath = true;
                return(new List <AiNode> {
                    startPoint, endPoint
                });
            }

            foundPath = false;

            PriorityQueue <AiNode> todo     = new PriorityQueue <AiNode>();
            List <AiNode>          doneList = new List <AiNode>();

            todo.Enqueue(startPoint);

            while (todo.Count != 0)
            {
                AiNode current = todo.Dequeue();
                doneList.Add(current);

                current.NodeState = AiNodeState.Closed;
                if (current == endPoint)
                {
                    foundPath = true;
                    float         debugCurrentCost = current.CurrentCost;
                    List <AiNode> ret = GeneratePath(endPoint);

                    ResetNodes(todo, doneList);


                    sw.Stop();
                    Logger.Log(DebugChannel.EngineAI | DebugChannel.Log, $"A* Iteration Found Path: ", 9);

                    WriteStatistics(nodesConsidered, iterations, sw.ElapsedMilliseconds, debugCurrentCost, ret.Count);

                    return(ret);
                }

                for (int i = 0; i < current.ConnectionCount; i++)
                {
                    AiNode connection = current.GetConnection(i);

                    if (!connection.Walkable || connection.NodeState == AiNodeState.Closed)
                    {
                        continue;
                    }

                    float connD = (connection.Owner.GetWorldPosition() - current.Owner.GetWorldPosition()).Length *
                                  connection.WalkCostMultiplier;
                    if (connection.NodeState == AiNodeState.Unconsidered)
                    {
                        connection.ParentNode = current;

                        connection.CurrentCost = current.CurrentCost + connD;

                        connection.EstimatedCost =
                            (connection.Owner.GetWorldPosition() - endPoint.Owner.GetWorldPosition()).Length;
                        connection.NodeState = AiNodeState.Open;
                        todo.Enqueue(connection);
                    }

                    if (current != connection) //Shouldnt be possible. but better check to avoid spinning forever
                    {
                        float newCost = current.CurrentCost + connD;
                        if (newCost < connection.CurrentCost)
                        {
                            connection.ParentNode  = current;
                            connection.CurrentCost = newCost;
                        }
                    }
                }

                iterations++;
                nodesConsidered++;
            }

            ResetNodes(todo, doneList);
            foundPath = false;
            sw.Stop();
            Logger.Log(DebugChannel.EngineAI | DebugChannel.Warning, $"A* Iteration did NOT find Path: ", 9);

            WriteStatistics(nodesConsidered, iterations, sw.ElapsedMilliseconds, 0, 0);
            return(new List <AiNode>());
        }