Exemple #1
0
        private static PathNode MakePath(MapWalkData walkData, Position start, Position target, int maxDistance, int range)
        {
            if (!walkData.IsCellWalkable(target))
            {
                return(null);
            }

            var path = BuildPath(walkData, start, target, maxDistance, range);

            //openList.Clear();
            openListPos.Clear();
            closedListPos.Clear();

            return(path);
        }
Exemple #2
0
        private static int CheckDirectPath(MapWalkData walkData, Position start, Position target, int maxDistance, int range, int startPos)
        {
            var pos = start;

            tempPath[startPos] = pos;
            var i = startPos + 1;

            while (i < maxDistance)
            {
                if (pos.X > target.X + range)
                {
                    pos.X--;
                }
                if (pos.X < target.X - range)
                {
                    pos.X++;
                }
                if (pos.Y > target.Y + range)
                {
                    pos.Y--;
                }
                if (pos.Y < target.Y - range)
                {
                    pos.Y++;
                }

                if (!walkData.IsCellWalkable(pos))
                {
                    return(0);
                }

                tempPath[i] = pos;
                i++;

                if (pos.SquareDistance(target) <= range)
                {
                    Profiler.Event(ProfilerEvent.PathFoundDirect);
                    return(i);
                }
            }

            return(0);
        }
Exemple #3
0
        public static int GetPath(MapWalkData walkData, Position start, Position target, Position[] pathOut, int range)
        {
            Profiler.Event(ProfilerEvent.PathfinderCall);

            if (start == target)
            {
                return(0);
            }

            if (Math.Abs(start.X - target.X) > MaxDistance || Math.Abs(start.Y - target.Y) > MaxDistance)
            {
                return(0);
            }

            var direct = CheckDirectPath(walkData, start, target, MaxDistance, range, 0);

            if (direct > 0)
            {
                if (pathOut == null)
                {
                    return(direct);
                }

                CopyTempPath(pathOut, direct);
#if DEBUG
                SanityCheck(pathOut, start, target, direct, range);
#endif
                return(direct);
            }

            var path = MakePath(walkData, start, target, MaxDistance, range);
            if (path == null)
            {
                return(0);
            }

            var steps = path.Steps + 1;

            if (pathOut == null)
            {
                return(steps);
            }

#if DEBUG
            if (path.Steps >= pathOut.Length)
            {
                ServerLogger.LogWarning($"Whoa! This isn't good. Steps is {path.Steps} but the array is {pathOut.Length}");
            }
#endif

            while (path != null)
            {
                pathOut[path.Steps] = path.Position;
                path = path.Parent;
            }

#if DEBUG
            SanityCheck(pathOut, start, target, steps, range);
#endif

            return(steps);
        }
Exemple #4
0
        //private static void InsertOpenNode(PathNode node)
        //{
        //	for (var i = 0; i < openList.Count; i++)
        //	{
        //		if (node.F < openList[i].F)
        //		{
        //			openList.Insert(i, node);
        //			return;
        //		}
        //	}

        //	openList.Add(node);
        //}

        private static PathNode BuildPath(MapWalkData walkData, Position start, Position target, int maxLength, int range)
        {
            if (nodeCache == null)
            {
                BuildCache();
            }

            cachePos         = MaxCacheSize;
            Pathfinder.range = range;

            //openList.Clear();
            openBag.Clear();
            openListPos.Clear();
            closedListPos.Clear();
            nodeLookup.Clear();

            var current = NextPathNode(null, start, CalcDistance(start, target));

            openBag.Add(current);
            //openList.Add(current);
            AddLookup(start, current);

            while (openBag.Count > 0 && !closedListPos.Contains(target))
            {
                //current = openList[0];
                current = openBag[0];
                openBag.RemoveFirst();
                //openList.RemoveAt(0);
                openListPos.Remove(current.Position);
                closedListPos.Add(current.Position);

                if (current.Steps > maxLength || current.Steps + current.Distance / 2 > maxLength)
                {
                    continue;
                }

                for (var x = -1; x <= 1; x++)
                {
                    for (var y = -1; y <= 1; y++)
                    {
                        if (x == 0 && y == 0)
                        {
                            continue;
                        }

                        var np = current.Position;
                        np.X += x;
                        np.Y += y;

                        if (np.X < 0 || np.Y < 0 || np.X >= walkData.Width || np.Y >= walkData.Height)
                        {
                            continue;
                        }

                        if (openListPos.Contains(np))
                        {
                            //the open list contains the neighboring cell. Check if the path from this node is better or not
                            var oldNode  = GetNode(np);
                            var dir      = (np - current.Position).GetDirectionForOffset();
                            var distance = CalcDistance(np, target);
                            var newF     = current.Score + 1 + distance + (dir.IsDiagonal() ? 0.4f : 0f);
                            if (newF < oldNode.F)
                            {
                                oldNode.Set(current, np, CalcDistance(np, target));                                 //swap the old parent to us if we're better
                            }

                            continue;
                        }

                        if (closedListPos.Contains(np))
                        {
                            continue;
                        }


                        if (!walkData.IsCellWalkable(np))
                        {
                            continue;
                        }

                        if (x == -1 && y == -1)
                        {
                            if (!walkData.IsCellWalkable(current.Position.X - 1, current.Position.Y) ||
                                !walkData.IsCellWalkable(current.Position.X, current.Position.Y - 1))
                            {
                                continue;
                            }
                        }

                        if (x == -1 && y == 1)
                        {
                            if (!walkData.IsCellWalkable(current.Position.X - 1, current.Position.Y) ||
                                !walkData.IsCellWalkable(current.Position.X, current.Position.Y + 1))
                            {
                                continue;
                            }
                        }

                        if (x == 1 && y == -1)
                        {
                            if (!walkData.IsCellWalkable(current.Position.X + 1, current.Position.Y) ||
                                !walkData.IsCellWalkable(current.Position.X, current.Position.Y - 1))
                            {
                                continue;
                            }
                        }

                        if (x == 1 && y == 1)
                        {
                            if (!walkData.IsCellWalkable(current.Position.X + 1, current.Position.Y) ||
                                !walkData.IsCellWalkable(current.Position.X, current.Position.Y + 1))
                            {
                                continue;
                            }
                        }

                        if (np.SquareDistance(target) <= range)
                        {
                            Profiler.Event(ProfilerEvent.PathFoundIndirect);
                            return(NextPathNode(current, np, 0));
                        }

                        var newNode = NextPathNode(current, np, CalcDistance(np, target));
                        //openList.Add(newNode);

                        //InsertOpenNode(newNode);

                        openBag.Add(newNode);
                        //openListPos.Add(np);
                        AddLookup(np, newNode);
                        closedListPos.Add(np);

                        //openList.Sort((a, b) => a.F.CompareTo(b.F));
                    }
                }
            }

            Profiler.Event(ProfilerEvent.PathNotFound);

            return(null);
        }