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); }
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); }
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); }
//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); }