コード例 #1
0
ファイル: DirectPathResult.cs プロジェクト: jdeter14/game1
        /// <summary>
        /// Factory method to create a result with a path
        /// </summary>
        /// <param name="pathPoints">The path points.</param>
        /// <param name="endWaypoint">The end way point.</param>
        /// <param name="originalRequest">The original request.</param>
        /// <returns>The result</returns>
        public static DirectPathResult CreateWithPath(Vector3[] pathPoints, Vector3 endWaypoint, IPathRequest originalRequest)
        {
            var res = new DirectPathResult();

            var path = new StackWithLookAhead<IPositioned>(pathPoints.Length);

            for (int i = pathPoints.Length - 1; i >= 0; i--)
            {
                path.Push(new Position(pathPoints[i]));
            }

            res.path = path;
            res.pendingWaypoints = new[] { endWaypoint };
            res.originalRequest = originalRequest;
            res.status = PathingStatus.Complete;

            return res;
        }
コード例 #2
0
ファイル: PathingEngineBase.cs プロジェクト: jdeter14/game1
        private void CompleteRequest(PathingStatus status)
        {
            if (status == PathingStatus.Complete)
            {
                StackWithLookAhead<IPositioned> path;
                var maxPathLength = Mathf.CeilToInt(_goal.g / (_goal.parent.cellSize * _costProvider.baseMoveCost));

                //Fix the actual destination so it does not overlap obstructions
                FixupGoal(_currentRequest);

                if (_currentRequest.usePathSmoothing)
                {
                    path = _smoother.Smooth(_goal, maxPathLength, _currentRequest);
                }
                else
                {
                    path = new StackWithLookAhead<IPositioned>(maxPathLength);

                    //Push the actual end position as the goal
                    path.Push(new Position(_currentRequest.to));

                    IPathNode current = _goal.predecessor;
                    while (current != null)
                    {
                        path.Push(current);
                        current = current.predecessor;
                    }

                    //Instead of testing for it in the while loop, just pop off the start node and replace it with the actual start position
                    if (path.count > 1)
                    {
                        path.Pop();
                    }

                    path.Push(new Position(_currentRequest.from));
                }

                _currentRequest.Complete(status, path);
            }
            else
            {
                _currentRequest.Complete(status, null);
            }

            _currentRequest = null;
        }
コード例 #3
0
ファイル: PathSmoother.cs プロジェクト: jdeter14/game1
        /// <summary>
        /// Smooths a path.
        /// </summary>
        /// <param name="goal">The goal node of the calculated path.</param>
        /// <param name="maxPathLength">Maximum length of the path.</param>
        /// <param name="request">The path request.</param>
        /// <returns>
        /// The path in smoothed form
        /// </returns>
        public StackWithLookAhead<IPositioned> Smooth(IPathNode goal, int maxPathLength, IPathRequest request)
        {
            var requesterAttributes = request.requester.attributes;
            var requesterRadius = request.requester.radius;

            //Next prune superfluous path nodes
            var reversePath = new List<IPositioned>(maxPathLength);

            var current = goal;
            var next = current.predecessor;

            int bends = -1;
            var prevDir = Vector3.zero;

            while (next != null)
            {
                var dir = next.position - current.position;

                if ((dir != prevDir) || (next is IPortalNode))
                {
                    reversePath.Add(current);
                    prevDir = dir;
                    bends++;
                }

                current = next;
                next = current.predecessor;
            }

            //Correct the end nodes and inject a mid point if too much was pruned (can happen on straight paths with no direction change, which can lead to obstacle collision if the unit is offset)
            if (reversePath.Count == 0)
            {
                reversePath.Add(new Position(request.to));
            }
            else
            {
                reversePath[0] = new Position(request.to);
            }

            if (reversePath.Count == 1 && bends <= 0)
            {
                reversePath.Add(goal.predecessor);
            }

            reversePath.Add(new Position(request.from));

            //Next see if we can reduce the path further by excluding unnecessary bends
            if (!request.preventDiagonalMoves)
            {
                var matrix = goal.parent;

                for (int i = 0; i < reversePath.Count - 2; i++)
                {
                    var c1 = reversePath[i];
                    var c2 = reversePath[i + 1];
                    var c3 = reversePath[i + 2];

                    var skip = AdjustIfPortal(c1, c2, c3);

                    if (skip > -1)
                    {
                        //One of the candidate nodes is a portal so skip to the node following the portal and resolve the grid at the other end of the portal.
                        //Since a portal node will never be the last node we can safely do this here. Since we are moving in the reverse direction here the portal will be on the other side.
                        i += skip;
                        matrix = ((IPortalNode)reversePath[i]).parent;
                        continue;
                    }

                    if (CanReducePath(c1, c3, requesterAttributes, requesterRadius, matrix))
                    {
                        reversePath[i + 1] = null;
                        i++;
                    }
                }
            }

            //Construct the final path replacing the start and goal nodes with the actual start and goal positions
            var path = new StackWithLookAhead<IPositioned>();

            for (int i = 0; i < reversePath.Count; i++)
            {
                var node = reversePath[i];
                if (node != null)
                {
                    path.Push(node);
                }
            }

            return path;
        }