Ejemplo n.º 1
0
    /// <summary>
    /// called when path from here to goal is found
    /// </summary>
    private void OnPathToGoalFound()
    {
        pathToGoal = pathShower.pathSave;

        // placing this here makes it so that enemy spawn
        // loop only begins after path is found
        StartCoroutine(EnemySpawnLoop());
    }
Ejemplo n.º 2
0
    // make with board/tilemap
    static FoundPath RunDjikstras(MapTile _start, MapTile _goal, List <MapTile> allTiles)
    {
        // setup
        MapTile currentNode = _start;

        currentNode.calculatedCost = 0;
        List <MapTile> unvisitedNodes = new List <MapTile>(allTiles);

        while (unvisitedNodes.Count > 0 && currentNode != _goal)
        {
            unvisitedNodes.Remove(currentNode);

            Debug.Assert(currentNode.Connections.Count <= 4); // take out later

            // all neighbors
            foreach (MapTile neighbor in currentNode.Connections)
            {
                if (neighbor.calculatedCost > 1000000)
                {
                    int newCost = currentNode.calculatedCost + neighbor.Data.traversalCost;
                    if (newCost < neighbor.calculatedCost)
                    {
                        neighbor.calculatedCost = newCost;
                        neighbor.previousTile   = currentNode;
                    }
                }
            }

            // next current
            currentNode = unvisitedNodes[0];
            foreach (MapTile currentCheck in unvisitedNodes)
            {
                if (currentCheck.calculatedCost < currentNode.calculatedCost)
                {
                    currentNode = currentCheck;
                }
            }
        }

        List <MapTile> _path    = GeneratePath(_start, _goal, false);
        FoundPath      toReturn = new FoundPath
        {
            start = _start,
            goal  = _goal,
            path  = _path
        };

        // cleanup
        foreach (MapTile tile in allTiles)
        {
            tile.ResetPathfinding();
        }

        return(toReturn);
    }
Ejemplo n.º 3
0
    private bool FindPath(Vector3 startPos, Vector3 endPos, float clampTol)
    {
        // re-number all the pathpoints
        Dictionary <GameObject, int> IDs = new Dictionary <GameObject, int>();
        int N = 0;

        foreach (GameObject pathPoint in pathPoints)
        {
            IDs[pathPoint] = N;
            ++N;
        }

        // init path matrix
        float[,] path = new float[pathPoints.Count, pathPoints.Count];
        for (int i = 0; i < N; ++i)
        {
            for (int j = 0; j < N; ++j)
            {
                path[i, j] = maxDistance;
            }
        }
        foreach (GameObject pathEdge in pathEdges)
        {
            GameObject p0 = pathEdge.GetComponent <PathEdge>().P0();
            GameObject p1 = pathEdge.GetComponent <PathEdge>().P1();

            int id0 = IDs[p0];
            int id1 = IDs[p1];
            path[id0, id1] = Distance(p0, p1);
            path[id1, id0] = path[id0, id1];
        }

        //int s = IDs[FindNearestPathPoint(startPos)];
        //int t = IDs[FindNearestPathPoint(endPos)];
        GameObject es = FindNearestPathEdge(startPos);
        GameObject et = FindNearestPathEdge(endPos);

        Debug.Log(es + " " + et);
        if (es == null || et == null)
        {
            return(false);
        }

        // move in the same "zone"
        if (es == et)
        {
            //Debug.Log("same");
            recentPath = new FoundPath();
            Vector3 validEndPos = Clamp(et.GetComponent <PathEdge>(), endPos);
            if (Vector3.Distance(validEndPos, endPos) > clampTol)
            {
                return(false);
            }
            recentPath.Insert(new DirectedPathEdgeOnPositions(startPos, validEndPos));
        }
        else
        {
            float[] d = new float[N];
            for (int i = 0; i < N; ++i)
            {
                d[i] = maxDistance;
            }
            int esp0 = IDs[es.GetComponent <PathEdge>().P0()];
            int esp1 = IDs[es.GetComponent <PathEdge>().P1()];
            int etp0 = IDs[et.GetComponent <PathEdge>().P0()];
            int etp1 = IDs[et.GetComponent <PathEdge>().P1()];
            d[esp0] = Vector3.Distance(es.GetComponent <PathEdge>().P0().transform.position, startPos);
            d[esp1] = Vector3.Distance(es.GetComponent <PathEdge>().P1().transform.position, startPos);
            //d[s] = 0;

            prePathPoint = new int[N];
            List <int> queue   = new List <int>();
            bool[]     inQueue = new bool[N];
            for (int i = 0; i < N; ++i)
            {
                inQueue[i]      = false;
                prePathPoint[i] = -1;
            }

            // SPFA starts from two points
            int head = 0;
            int tail = 0;
            queue.Add(esp0);
            ++tail;
            inQueue[esp0] = true;
            queue.Add(esp1);
            ++tail;
            inQueue[esp1] = true;
            //queue.Add(s);
            //++tail;
            //inQueue[s] = true;

            while (head < tail)
            {
                int o = queue[head];
                inQueue[o] = false;
                for (int i = 0; i < N; ++i)
                {
                    if (d[i] > d[o] + path[o, i])
                    {
                        d[i] = d[o] + path[o, i];
                        if (!inQueue[i])
                        {
                            queue.Add(i);
                            inQueue[i] = true;
                            ++tail;
                            prePathPoint[i] = o;
                        }
                    }
                }
                ++head;
            }

            // two end points - choose the nearer one
            float endDis0 = d[etp0] + Vector3.Distance(et.GetComponent <PathEdge>().P0().transform.position, endPos);
            float endDis1 = d[etp1] + Vector3.Distance(et.GetComponent <PathEdge>().P1().transform.position, endPos);
            //Debug.Log(endDis0 + " " + endDis1);
            if (endDis0 >= maxDistance && endDis1 >= maxDistance)
            {
                return(false);
            }

            // construct result path
            recentPath = new PointBasedFoundPath();
            int curPoint = etp0;
            if (endDis0 > endDis1)
            {
                curPoint = etp1;
            }

            Vector3 validEndPos = Clamp(et.GetComponent <PathEdge>(), endPos);
            if (Vector3.Distance(validEndPos, endPos) > clampTol)
            {
                return(false);
            }

            recentPath.Insert(new DirectedPathEdgeOnObjectAndPosition(pathPoints[curPoint], validEndPos));

            while (true)
            {
                int prePoint = prePathPoint[curPoint];
                if (prePoint != -1)
                {
                    recentPath.Insert(new DirectedPathEdgeOnTwoObjects(pathPoints[prePoint], pathPoints[curPoint]));
                }
                else
                {
                    break;
                }
                curPoint = prePathPoint[curPoint];
            }
            recentPath.Insert(new DirectedPathEdgeOnPositionAndObject(startPos, pathPoints[curPoint]));
        }

        return(true);
    }
Ejemplo n.º 4
0
    public ICollection <Vector3> GetPath(Vector3 from, Vector3 to, Vector3 halfExtends)
    {
        FoundPath fp = foundPaths.Where(x => x.From == from && x.To == to && x.HalfExtends == halfExtends).FirstOrDefault();

        if (fp != null)
        {
            return(fp.Path.ToList());
        }

        List <PathfindingTile> closedList = new List <PathfindingTile>();
        List <PathfindingTile> openList   = new List <PathfindingTile>();


        openList.Add(new PathfindingTile(from, EstimateCosts(from, to), null));

        int limit        = 10000;
        int limitCounter = 0;

        while (openList.Where(x => x.Position == to).Count() == 0)
        {
            PathfindingTile   tileToCheck = openList.OrderBy(x => x.EstimatedCosts).First();
            PathfindingTile[] neigh       = GetNeighbors(tileToCheck, to, halfExtends);
            openList.AddRange(neigh.Where(o => closedList.Where(c => c.Position == o.Position).Count() == 0));
            openList.Remove(tileToCheck);
            closedList.Add(tileToCheck);

            limitCounter++;

            if (limitCounter > limit)
            {
                break;
            }
        }

        List <Vector3>  points    = new List <Vector3>();
        PathfindingTile nextTile  = openList.OrderBy(x => x.EstimatedCosts).First();
        bool            pathFound = false;

        while (!pathFound)
        {
            points.Add(nextTile.Position);

            if (nextTile.LastTile == null || nextTile.LastTile.Position == from)
            {
                pathFound = true;
                break;
            }

            nextTile = nextTile.LastTile;
        }

        int counter = 0;
        List <KeyValuePair <int, Vector3> > pointsWithOrder = new List <KeyValuePair <int, Vector3> >();

        for (var i = points.Count - 1; i >= 0; i--)
        {
            pointsWithOrder.Add(new KeyValuePair <int, Vector3>(counter, points[i]));
            counter++;
        }

        List <Vector3> path = pointsWithOrder.OrderBy(x => x.Key).Select(x => x.Value).ToList();

        foundPaths.Add(new FoundPath(from, to, halfExtends, path.ToArray()));
        return(path);
    }
Ejemplo n.º 5
0
    public void GreedyManhattanAlgorithm(Vector2Int start, Vector2Int end)
    {
        Queue <Vector2Int> frontier = new Queue <Vector2Int>();

        frontier.Enqueue(start);

        Dictionary <Vector2Int, Vector2Int> cameFrom = new Dictionary <Vector2Int, Vector2Int>();

        cameFrom.Add(start, start);

        List <Vector2Int> visited = new List <Vector2Int>();

        while (frontier.Count != 0)
        {
            Vector2Int current = frontier.Dequeue();

            visited.Add(current);
            pathFollowed.Add(current);

            List <Vector2Int> neighbours = GetNeighbours(current);

            Vector2Int cameFromLocal;
            cameFrom.TryGetValue(current, out cameFromLocal);

            neighbours.Remove(cameFromLocal);

            //Remove visited neighbours
            List <Vector2Int> neighboursToRemove = new List <Vector2Int>();
            foreach (Vector2Int neighbour in neighbours)
            {
                if (visited.Contains(neighbour))
                {
                    neighboursToRemove.Add(neighbour);
                }
            }
            foreach (Vector2Int neighbour in neighboursToRemove)
            {
                neighbours.Remove(neighbour);
                FoundPath.Remove(current);
            }

            //Sort neighbours so the element closest to the end (Using Manhattan distance) is first
            neighbours.Sort(delegate(Vector2Int a, Vector2Int b)
            {
                int aManhattan = PathfinderHelper.ManhattanDistance(a.x, a.y, end.x, end.y);
                int bManhattan = PathfinderHelper.ManhattanDistance(b.x, b.y, end.x, end.y);

                if (aManhattan > bManhattan)
                {
                    return(1);
                }
                if (aManhattan < bManhattan)
                {
                    return(-1);
                }
                return(0);
            });

            //If there is a neighbour, check him. Otherwise, backtrack
            if (neighbours.Count > 0)
            {
                Vector2Int nextNeighbour = neighbours[0];
                FoundPath.Add(current);
                if (nextNeighbour == end)
                {
                    pathFollowed.Add(nextNeighbour);
                    return;
                }
                else
                {
                    frontier.Enqueue(nextNeighbour);
                    cameFrom.Add(nextNeighbour, current);
                    visited.Add(current);
                }
            }
            else
            {
                frontier.Enqueue(cameFromLocal);
                FoundPath.Remove(current);
            }
        }
    }
Ejemplo n.º 6
0
    IEnumerator PathfindingAnimation()
    {
        if (null != currentTile.previousTile)
        {
            currentTile.previousTile.tileStatus = TileStatus.clear;
        }


        while (unvsitedTiles.Count > 0 && currentTile != goal)
        {
            unvsitedTiles.Remove(currentTile);

            Debug.Assert(currentTile.Connections.Count <= 4); // take out later

            // all neighbors
            foreach (MapTile neighbor in currentTile.Connections)
            {
                if (neighbor.calculatedCost > 1000000)
                {
                    int newCost = currentTile.calculatedCost + neighbor.Data.traversalCost;
                    if (newCost < neighbor.calculatedCost)
                    {
                        neighbor.calculatedCost = newCost;
                        neighbor.previousTile   = currentTile;
                    }
                }
            }

            // currentTile.tileStatus = TileStatus.clear;
            foreach (MapTile tile in currentTile.Connections)
            {
                tile.tileStatus = TileStatus.none;
            }

            // next current
            currentTile = unvsitedTiles[0];
            foreach (MapTile currentCheck in unvsitedTiles)
            {
                if (currentCheck.calculatedCost < currentTile.calculatedCost)
                {
                    currentTile            = currentCheck;
                    currentTile.tileStatus = TileStatus.current;
                    foreach (MapTile neighbor in currentTile.Connections)
                    {
                        neighbor.tileStatus = TileStatus.next;
                    }
                }
            }

            yield return(new WaitForSeconds(waitTime));
        }

        List <MapTile> path     = Pathfinder.GeneratePath(start, goal, false);
        FoundPath      toReturn = new FoundPath
        {
            start = start,
            goal  = goal,
            path  = path
        };

        // cleanup
        foreach (MapTile tile in allTiles)
        {
            tile.ResetPathfinding();
        }

        pathSave = toReturn;

        pathFound?.Invoke();
    }