Пример #1
0
        private RegionPath RetracePath(RegionItem end)
        {
            RegionPath        path = new RegionPath();
            RegionItem        item = end;
            List <RegionItem> res  = new List <RegionItem>();

            while (item != null)
            {
                res.Add(item);
                item = item.parent;
            }
            res.Reverse();
            foreach (RegionItem i in res)
            {
                path.Add(new PathItem(Position + i.LocalCoordinate, i.Layer));
            }
            return(path);
        }
Пример #2
0
        /// <summary>
        /// Поиск пути из точки в точку
        /// </summary>
        /// <param name="from">Start local point</param>
        /// <param name="to">End local point</param>
        /// <param name="comparer">Point comparer</param>
        /// <returns>Возвращает путь в глобальных координатах</returns>
        public RegionPath GetPath(Vector2i from, Vector2i to, IRegion2DItemComparer comparer, IHeuristic2D heuristic, LayerMask walkable, LayersValues weights, LayerMask priority)
        {
            RegionPath path  = null;
            RegionItem start = GetItem(from);
            RegionItem end   = GetItem(to);

            if (start == null || end == null ||
                !walkable.Contains(start.Layer) || !walkable.Contains(end.Layer))
            {
                return(null);
            }
            if (comparer == null)
            {
                comparer = new OptimalRegion2DItemsComparer();
            }
            if (heuristic == null)
            {
                heuristic = new Manhatan2D();
            }

            byte closedvalue = IncrementCurrentIteration;

            sbyte[,] direction = new sbyte[8, 2] {
                { 0, -1 }, { 1, 0 }, { 0, 1 }, { -1, 0 }, { 1, -1 }, { 1, 1 }, { -1, 1 }, { -1, -1 }
            };
            MyTreeQueue <RegionItem> opened = new MyTreeQueue <RegionItem>(comparer);
            //TreeQueue<RegionItem> opened = new TreeQueue<RegionItem>(comparer);
            RegionItem parent = null;

            start.g      = 0;
            start.f      = heuristic.GetHeuristic(from, to);
            start.parent = null;
            opened.Push(start);

            int nx;
            int ny;

            while (opened.Count > 0)
            {
                parent        = opened.Pop();   // Извлекаем очередной наименьший блок (на первом шаге это стартовый)
                parent.closed = closedvalue;    // Отмечаем его как просмотренный ранее
                parent.opened = 0;              // Изьять из списка кандидатов на просмотр

                if (parent.LocalCoordinate.x == end.LocalCoordinate.x && parent.LocalCoordinate.y == end.LocalCoordinate.y)
                {
                    path = RetracePath(end);
                    break;
                }

                for (int i = 0; i < 8; i++)     // Просматриваем всех соседей
                {
                    nx = parent.LocalCoordinate.x + direction[i, 0];
                    ny = parent.LocalCoordinate.y + direction[i, 1];

                    if (nx < 0 || ny < 0 || nx >= xScale || ny >= yScale)
                    {
                        continue;
                    }
                    RegionItem newnode = GetItem(new Vector2i(nx, ny));

                    // Если блок был просмотрен ранее или поверхность не проходима
                    if (newnode.closed == closedvalue || !walkable.Contains(newnode.Layer))
                    {
                        continue;
                    }
                    // Получаем базовый штраф поверхности (если приоритетная поверхность, то штраф минимальный)
                    int penalti = (priority.Contains(newnode.Layer)) ? weights.MinValue : weights.GetValue(newnode.Layer);
                    // Вычисляем пройденный путь в штрафах до соседа
                    int g = parent.g + penalti;
                    // Если в списке кандидатов на просмотр и новый вес больше старого - пропускаем
                    if (newnode.opened == closedvalue && newnode.g <= g)
                    {
                        continue;
                    }
                    // Получаем оставшееся расстояние
                    double f = heuristic.GetHeuristic(new Vector2i(newnode.LocalCoordinate.x, newnode.LocalCoordinate.y), new Vector2i(end.LocalCoordinate.x, end.LocalCoordinate.y));

                    newnode.g      = g;
                    newnode.f      = f;
                    newnode.parent = parent;
                    // Поместить в список кандидатов на просмотр
                    if (newnode.opened != closedvalue)
                    {
                        opened.Push(newnode);
                        newnode.opened = closedvalue;
                    }
                }
            }
            return(path);
        }