public static float?GetTileCost(PathfindingArgs pathfindingArgs, PathfindingNode start, PathfindingNode end)
        {
            if (!pathfindingArgs.NoClip && !Traversable(pathfindingArgs.CollisionMask, pathfindingArgs.Access, end))
            {
                return(null);
            }

            if (!pathfindingArgs.AllowSpace && end.TileRef.Tile.IsEmpty)
            {
                return(null);
            }

            var cost = 1.0f;

            switch (pathfindingArgs.AllowDiagonals)
            {
            case true:
                cost *= OctileDistance(end, start);
                break;

            // Manhattan distance
            case false:
                cost *= ManhattanDistance(end, start);
                break;
            }

            return(cost);
        }
        /// <summary>
        /// Ask for the pathfinder to gimme somethin
        /// </summary>
        /// <param name="pathfindingArgs"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Job <Queue <TileRef> > RequestPath(PathfindingArgs pathfindingArgs, CancellationToken cancellationToken)
        {
            var startNode = GetNode(pathfindingArgs.Start);
            var endNode   = GetNode(pathfindingArgs.End);
            var job       = new AStarPathfindingJob(0.003, startNode, endNode, pathfindingArgs, cancellationToken);

            _pathfindingQueue.EnqueueJob(job);

            return(job);
        }
Esempio n. 3
0
        /// <summary>
        /// Gets all of the tiles in range that can we access
        /// </summary>
        /// If you want Dikstra then add distances.
        /// Doesn't use the JobQueue as it will generally be encapsulated by other jobs
        /// <param name="pathfindingArgs"></param>
        /// <param name="range"></param>
        /// <param name="fromStart">Whether we traverse from the starting tile or the end tile</param>
        /// <returns></returns>
        public static IEnumerable <PathfindingNode> GetNodesInRange(PathfindingArgs pathfindingArgs, bool fromStart = true)
        {
            var pathfindingSystem = EntitySystem.Get <PathfindingSystem>();
            // Don't need a priority queue given not looking for shortest path
            var             openTiles   = new Queue <PathfindingNode>();
            var             closedTiles = new HashSet <TileRef>();
            PathfindingNode startNode;

            if (fromStart)
            {
                startNode = pathfindingSystem.GetNode(pathfindingArgs.Start);
            }
            else
            {
                startNode = pathfindingSystem.GetNode(pathfindingArgs.End);
            }

            PathfindingNode currentNode;

            openTiles.Enqueue(startNode);

            while (openTiles.Count > 0)
            {
                currentNode = openTiles.Dequeue();

                foreach (var neighbor in currentNode.GetNeighbors())
                {
                    // No distances stored so can just check closed tiles here
                    if (closedTiles.Contains(neighbor.TileRef))
                    {
                        continue;
                    }
                    closedTiles.Add(currentNode.TileRef);

                    // So currently tileCost gets the octile distance between the 2 so we'll also use that for our range check
                    var tileCost  = PathfindingHelpers.GetTileCost(pathfindingArgs, startNode, neighbor);
                    var direction = PathfindingHelpers.RelativeDirection(neighbor, currentNode);

                    if (tileCost == null ||
                        tileCost > pathfindingArgs.Proximity ||
                        !PathfindingHelpers.DirectionTraversable(pathfindingArgs.CollisionMask, pathfindingArgs.Access, currentNode, direction))
                    {
                        continue;
                    }

                    openTiles.Enqueue(neighbor);
                    yield return(neighbor);
                }
            }
        }
        public static bool TryEndNode(ref PathfindingNode endNode, PathfindingArgs pathfindingArgs)
        {
            if (!Traversable(pathfindingArgs.CollisionMask, pathfindingArgs.Access, endNode))
            {
                if (pathfindingArgs.Proximity > 0.0f)
                {
                    foreach (var node in BFSPathfinder.GetNodesInRange(pathfindingArgs, false))
                    {
                        endNode = node;
                        return(true);
                    }
                }

                return(false);
            }

            return(true);
        }
Esempio n. 5
0
        public static bool TryEndNode(ref PathfindingNode endNode, PathfindingArgs pathfindingArgs)
        {
            if (!Traversable(pathfindingArgs.CollisionMask, endNode.CollisionMask))
            {
                if (pathfindingArgs.Proximity > 0.0f)
                {
                    // TODO: Should make this account for proximities,
                    // probably some kind of breadth-first search to find a valid one
                    foreach (var(direction, node) in endNode.Neighbors)
                    {
                        if (Traversable(pathfindingArgs.CollisionMask, node.CollisionMask))
                        {
                            endNode = node;
                            return(true);
                        }
                    }
                }

                return(false);
            }

            return(true);
        }