Ejemplo n.º 1
0
        public void FindPath(PathRequest request, Action <PathResult> callback)
        {
            Stopwatch sw = new Stopwatch();

            sw.Start();

            Vector3[] waypoints   = new Vector3[0];
            bool      pathSuccess = false;

            Node startNode  = grid.NodeFromWorldPoint(request.pathStart);
            Node targetNode = grid.NodeFromWorldPoint(request.pathEnd);

            startNode.parent = startNode;


            if (startNode.walkable && targetNode.walkable)
            {
                Heap <Node>    openSet   = new Heap <Node>(grid.MaxSize);
                HashSet <Node> closedSet = new HashSet <Node>();
                openSet.Add(startNode);

                while (openSet.Count > 0)
                {
                    Node currentNode = openSet.RemoveFirst();
                    closedSet.Add(currentNode);

                    if (currentNode == targetNode)
                    {
                        sw.Stop();
                        //print ("Path found: " + sw.ElapsedMilliseconds + " ms");
                        pathSuccess = true;
                        break;
                    }

                    foreach (Node neighbour in grid.GetNeighbours(currentNode))
                    {
                        if (!neighbour.walkable || closedSet.Contains(neighbour))
                        {
                            continue;
                        }

                        float newMovementCostToNeighbour = currentNode.gCost + GetDistance(currentNode, neighbour) + neighbour.movementPenalty;
                        if (newMovementCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))
                        {
                            neighbour.gCost  = newMovementCostToNeighbour;
                            neighbour.hCost  = GetDistance(neighbour, targetNode);
                            neighbour.parent = currentNode;

                            if (!openSet.Contains(neighbour))
                            {
                                openSet.Add(neighbour);
                            }
                            else
                            {
                                openSet.UpdateItem(neighbour);
                            }
                        }
                    }
                }
            }
            if (pathSuccess)
            {
                waypoints   = RetracePath(startNode, targetNode);
                pathSuccess = waypoints.Length > 0;
            }
            callback(new PathResult(waypoints, pathSuccess, request.callback));
        }
Ejemplo n.º 2
0
        public void FindPath(PathRequest request, Action <PathResult> callback)
        {
            Stopwatch sw = new Stopwatch();

            sw.Start();

            Vector3[] waypoints   = new Vector3[0];
            bool      pathSuccess = false;

            Node2D startNode = grid.NodeFromWorldPoint(request.pathStart);
            var    endNodes  = grid.NodesFromWorldBound(request.pathEnd, request.endBounds);

            UnityEngine.Debug.Log("nodes in end node: " + endNodes.Length);
            Node2D[] targetNode = endNodes.Where(n => n.walkable).ToArray();
            UnityEngine.Debug.Log("usable target nodes: " + targetNode.Length);
            Node2D endNode = startNode;

            try
            {
                endNode = targetNode[0];

                startNode.parent = startNode;


                if (startNode.walkable && targetNode != null && targetNode.Length > 0)
                {
                    Heap <Node2D>    openSet   = new Heap <Node2D>(grid.MaxSize);
                    HashSet <Node2D> closedSet = new HashSet <Node2D>();
                    openSet.Add(startNode);

                    while (openSet.Count > 0)
                    {
                        Node2D currentNode = openSet.RemoveFirst();
                        closedSet.Add(currentNode);

                        if (targetNode.Contains(currentNode))
                        {
                            sw.Stop();
                            UnityEngine.Debug.Log("Path found: " + sw.ElapsedMilliseconds + " ms");
                            pathSuccess = true;
                            endNode     = currentNode;
                            break;
                        }

                        foreach (Node2D neighbour in grid.GetNeighbours(currentNode))
                        {
                            if (!neighbour.walkable || closedSet.Contains(neighbour))
                            {
                                continue;
                            }

                            int newMovementCostToNeighbour = currentNode.gCost + GetDistance(currentNode, neighbour) + neighbour.movementPenalty;
                            if (newMovementCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))
                            {
                                neighbour.gCost  = newMovementCostToNeighbour;
                                neighbour.hCost  = GetDistance(neighbour, targetNode);
                                neighbour.parent = currentNode;

                                if (!openSet.Contains(neighbour))
                                {
                                    openSet.Add(neighbour);
                                }
                                else
                                {
                                    openSet.UpdateItem(neighbour);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                UnityEngine.Debug.Log("No usable end nodes");
                callback(new PathResult(waypoints, pathSuccess, request.callback));
            }
            if (pathSuccess)
            {
                waypoints   = RetracePath(startNode, endNode);
                pathSuccess = waypoints.Length > 0;
            }
            callback(new PathResult(waypoints, pathSuccess, request.callback));
        }
Ejemplo n.º 3
0
        public void CalculateFill2D(List <Vector2Int> path, Vector2Int from, bool verticalMovement)
        {
            Heap        open   = new Heap(heapSize);
            HashSet <T> closed = new HashSet <T>();

            T start = grid[from.x, from.y],
              current;

            int xLength = grid.GetLength(0),
                yLength = grid.GetLength(1);

            open.Add(grid[from.x, from.y]);

            Func <int, int, bool> isOutOfBounds = delegate(int x, int y)
            {
                return(x < 0 || x >= xLength || y < 0 || y >= yLength);
            };

            Action <int, int> tryAddNeighbour = delegate(int x, int y)
            {
                if (isOutOfBounds(x, y))
                {
                    return;
                }
                if (!grid[x, y].Walkable)
                {
                    return;
                }
                if (closed.Contains(grid[x, y]))
                {
                    return;
                }
                if (open.Contains(grid[x, y]))
                {
                    return;
                }
                open.Add(grid[x, y]);
            };

            Vector2Int currentPosition;

            while (open.Count > 0)
            {
                current = open.Get();
                closed.Add(current);

                currentPosition = current.Position;

                tryAddNeighbour(currentPosition.x, currentPosition.y + 1);
                tryAddNeighbour(currentPosition.x + 1, currentPosition.y);
                tryAddNeighbour(currentPosition.x, currentPosition.y - 1);
                tryAddNeighbour(currentPosition.x - 1, currentPosition.y);

                if (!verticalMovement)
                {
                    continue;
                }

                tryAddNeighbour(currentPosition.x + 1, currentPosition.y + 1);
                tryAddNeighbour(currentPosition.x + 1, currentPosition.y - 1);
                tryAddNeighbour(currentPosition.x - 1, currentPosition.y - 1);
                tryAddNeighbour(currentPosition.x - 1, currentPosition.y + 1);
            }

            foreach (T node in closed)
            {
                path.Add(node.Position);
            }
        }
Ejemplo n.º 4
0
        public void Calculate2D(List <Vector2Int> path, Vector2Int from, Vector2Int to, bool verticalMovement)
        {
            Heap        open   = new Heap(heapSize);
            HashSet <T> closed = new HashSet <T>();

            T start = grid[from.x, from.y],
              end   = grid[to.x, to.y];

            int xLength = grid.GetLength(0),
                yLength = grid.GetLength(1);

            open.Add(grid[from.x, from.y]);

            T current = null;

            Func <int, int, bool> isOutOfBounds = delegate(int x, int y)
            {
                return(x < 0 || x >= xLength || y < 0 || y >= yLength);
            };

            Func <T, T, T> setItem = delegate(T item, T parent)
            {
                item.Parent = parent.Position;
                item.G      = Vector2.Distance(item.Position, start.Position);
                item.H      = Vector2.Distance(item.Position, end.Position);
                return(item);
            };

            Action <int, int> TryAddNeighbour = delegate(int x, int y)
            {
                x += current.Position.x;
                y += current.Position.y;

                if (isOutOfBounds(x, y))
                {
                    return;
                }
                if (!grid[x, y].Walkable)
                {
                    return;
                }
                if (closed.Contains(grid[x, y]))
                {
                    return;
                }
                if (open.Contains(grid[x, y]))
                {
                    return;
                }

                // Set variables
                grid[x, y] = setItem(grid[x, y], current);
                open.Add(grid[x, y]);
            };

            // Keep getting current's parent until the start position has been found
            while (open.Count > 0)
            {
                current = open.Get();
                closed.Add(current);

                if (current.Position == end.Position)
                {
                    // When the start position is found it means that the complete path has been added
                    while (!current.Equals(start))
                    {
                        path.Add(current.Position);
                        current = grid[current.Parent.x, current.Parent.y];
                    }
                    return;
                }

                // Top
                TryAddNeighbour(0, 1);
                // Right
                TryAddNeighbour(1, 0);
                // Bottom
                TryAddNeighbour(0, -1);
                //Left
                TryAddNeighbour(-1, 0);

                if (verticalMovement)
                {
                    // Top Right
                    TryAddNeighbour(1, 1);
                    // Right Bottom
                    TryAddNeighbour(1, -1);
                    // Bottom Left
                    TryAddNeighbour(-1, -1);
                    //Left Top
                    TryAddNeighbour(-1, 1);
                }
            }

            return;
        }
Ejemplo n.º 5
0
        private void FindPathInternal(int requestId)
        {
            bool pathFound = false;

            PathRequestData prd      = _pathRequestDictionary[requestId];
            PathData        pathData = null;

            Node startNode = Nodes[prd.startCell.GridPosition.x, prd.startCell.GridPosition.y];
            Node endNode   = Nodes[prd.endCell.GridPosition.x, prd.endCell.GridPosition.y];

            Heap <Node>    openSet  = new Heap <Node>(_gridWidth * _gridHeight);
            HashSet <Node> closeSet = new HashSet <Node>();

            openSet.Add(startNode);

            while (openSet.Count > 0)
            {
                Node currentNode = openSet.RemoveFirst();
                closeSet.Add(currentNode);

                if (currentNode == endNode)
                {
                    var       retracedPath = RetracePath(startNode, endNode);
                    Vector3[] waypoints    = PathToVector3Array(retracedPath);

                    if (waypoints == null)
                    {
                        retracedPath.Add(endNode);
                        waypoints = new Vector3[1] {
                            endNode.CellObj.transform.position
                        };
                    }

                    pathData = new PathData(waypoints, retracedPath);
                    prd.callback(true, pathData);
                    pathFound = true;
                    break;
                }


                foreach (Node neighbour in GetNeighbours(currentNode))
                {
                    if (closeSet.Contains(neighbour))
                    {
                        continue;
                    }

                    int hCostToNeighbor = neighbour.CellObj.Cost;

                    if (prd.ignoreTemplateList != null && neighbour.CellObj.IsOccupied)
                    {
                        if (prd.ignoreTemplateList.Count(template => template.Equals(neighbour.CellObj.Occupant.TemplateID)) > 0)
                        {
                            hCostToNeighbor = 1;
                        }
                    }

                    int movementCostToNeighbour = currentNode.GCost + hCostToNeighbor;

                    if (movementCostToNeighbour < neighbour.GCost || !openSet.Contains(neighbour))
                    {
                        neighbour.GCost = movementCostToNeighbour;
                        neighbour.HCost = GetDistance(neighbour, endNode);

                        neighbour.Parent = currentNode;

                        if (!openSet.Contains(neighbour))
                        {
                            openSet.Add(neighbour);
                        }
                        else
                        {
                            openSet.UpdateItem(neighbour);
                        }
                    }
                }
            }

            if (!pathFound)
            {
                pathData = new PathData(new Vector3[1] {
                    endNode.CellObj.transform.position
                }, new List <Node>(1)
                {
                    endNode
                });
                prd.callback(false, pathData);
            }

            _pathRequestDictionary.Remove(requestId);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// A* pathfinding algorithm.
        /// </summary>
        /// <param name="request">PathRequest object.</param>
        /// <param name="callback">Callback object.</param>
        public void FindPath(PathRequest request, Action <PathResult> callback)
        {
            Stopwatch sw = new Stopwatch();

            sw.Start();

            List <Node> waypoints   = new List <Node>();
            bool        pathSuccess = false;

            Node startNode  = _aGrid.getNode(request.pathStart);
            Node targetNode = _aGrid.getNode(request.pathEnd);

            startNode.parent = startNode;


            if (targetNode.GetState() == Enums.TileState.FREE)
            {
                Heap <Node>    openSet   = new Heap <Node>(_aGrid.MaxSize);
                HashSet <Node> closedSet = new HashSet <Node>();
                openSet.Add(startNode);

                while (openSet.Count > 0)
                {
                    Node currentNode = openSet.RemoveFirst();
                    closedSet.Add(currentNode);

                    if (currentNode == targetNode)
                    {
                        sw.Stop();
                        //print ("Path found: " + sw.ElapsedMilliseconds + " ms");
                        pathSuccess = true;
                        break;
                    }

                    foreach (Node neighbour in _aGrid.GetNeighbours(currentNode))
                    {
                        if (neighbour.GetState() != Enums.TileState.FREE || closedSet.Contains(neighbour))
                        {
                            continue;
                        }

                        int newMovementCostToNeighbour =
                            currentNode.gCost + GetDistance(currentNode, neighbour) + neighbour.movementPenalty;
                        if (newMovementCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))
                        {
                            neighbour.gCost  = newMovementCostToNeighbour;
                            neighbour.hCost  = GetDistance(neighbour, targetNode);
                            neighbour.parent = currentNode;

                            if (!openSet.Contains(neighbour))
                            {
                                openSet.Add(neighbour);
                            }
                            else
                            {
                                openSet.UpdateItem(neighbour);
                            }
                        }
                    }
                }
            }

            if (pathSuccess)
            {
                waypoints   = RetracePath(startNode, targetNode);
                pathSuccess = waypoints.Count > 0;
            }

            callback(new PathResult(waypoints, pathSuccess, request.parameter, request.callback));
        }