예제 #1
0
 //  если путь не найден, запускается таймер на повторный поиск пути
 public void OnPathNotFound(FinishNotFoundReasons reason)
 {
     if (attemptCount == 0 || Vector2Int.Distance(this.gridPosition, gridFinishPosition) <= GameConstants.StopMoveMinDistance)
     {
         return;
     }
     attemptCount--;
     timer.SetTimer(reason == FinishNotFoundReasons.Blocked ? GameConstants.PathFindBlockedTime : GameConstants.PathFindAttemptTime);
 }
예제 #2
0
    /// <summary>
    /// Функция поиска пути
    /// </summary>
    public void FindPath()
    {
        startTime = DateTime.UtcNow;  //  получение времени начала работы
        FinishNotFoundReasons notFoundReason = FinishNotFoundReasons.None;

        bool[,] scannedCells = new bool[GameParams.Width, GameParams.Length];    //  просмотренные ячейки
        PriorityQueue <NavGridPoint> queue = new PriorityQueue <NavGridPoint>(); //  очередь с приоритетом из навигационных точек
        NavGridPoint point = new NavGridPoint(start, 0), movePoint;

        point.distance = GetDistance(start, finish);  //  получение дистанции между стартом и финишом
        queue.Add(point);
        scannedCells[start.x, start.y] = true;
        //  пока очередь не пустая, поиск пути актуален и поток не должен быть завершён
        while (queue.Count != 0 && IsActual && (FindThread == null || (FindThread.ThreadState & ThreadState.AbortRequested) == 0))
        {
            //  если финиш занят, выходим из цикла
            if (TerrainNavGrid.Instance.IsCellUsed(finish))
            {
                notFoundReason = FinishNotFoundReasons.FinishUsed;
                break;
            }
            point = queue.GetMin();
            //  если текущая позиция равна финишу, то выходим из цикла
            if (point.Position == finish)
            {
                IsPathFound = true;
                break;
            }
            if (IsPositionBlocked(point.Position))
            {
                notFoundReason = FinishNotFoundReasons.Blocked;
                break;
            }
            //  находим соседние клетки, ближайшие к финишу
            foreach (Vector2Int move in MoveArray)
            {
                movePoint = new NavGridPoint(point.Position + move, point.order + 1);

                if (!IsPointInField(movePoint.Position) || TerrainNavGrid.Instance.IsCellUsed(movePoint.Position) ||
                    TerrainHeightMap.Instance.GetHeight(movePoint.Position) >
                    TerrainHeightMap.Instance.GetHeight(point.Position) + maxHeight)
                {
                    continue;
                }
                //  пропускает поинт, если он вне карты, занят или выше текущей позиции

                //float heightDist = TerrainHeightMap.Instance.GetHeight(movePoint.Position) - TerrainHeightMap.Instance.GetHeight(point.Position);
                //if (heightDist < 0) heightDist = 0;
                movePoint.oldPoint = point;
                movePoint.distance = GetDistance(movePoint.Position, finish) /* + heightDist*/;
                if (scannedCells[movePoint.Position.x, movePoint.Position.y]) //  если позиция просмотрена
                {
                    if (queue.Contains(movePoint))                            //  если в очереди уже есть такая позиция, то берётся ближайшая к финишу
                    {
                        NavGridPoint remove = queue.Find(movePoint);
                        if (remove.Weight < movePoint.Weight)
                        {
                            continue;
                        }
                        queue.Remove(remove);
                        queue.Add(movePoint);
                    }
                    continue;
                }
                scannedCells[movePoint.Position.x, movePoint.Position.y] = true;
                queue.Add(movePoint);
                //  добавление поинта в очередь с приоритетом
            }
        }
        IsComplete = true;
        if (IsPathFound)  //  если путь найден, получаем список координат
        {
            while (point.oldPoint != null)
            {
                path.Add(point.Position);
                point = point.oldPoint;
            }
            if (onPathfound == null)
            {
                return;
            }
            onPathfound.BeginInvoke(path, null, null);
        }
        else
        {
            // иначе сообщаем причину
            if (notFoundReason == FinishNotFoundReasons.None)
            {
                notFoundReason = FinishNotFoundReasons.PathNotFound;
            }
            if (onPathNotFound == null)
            {
                return;
            }
            onPathNotFound.BeginInvoke(notFoundReason, null, null);
        }
    }