public static bool TryEndNode(ref PathfindingNode endNode, PathfindingArgs pathfindingArgs) { if (!Traversable(pathfindingArgs.CollisionMask, pathfindingArgs.Access, endNode)) { if (pathfindingArgs.Proximity > 0.0f) { // TODO: Should make this account for proximities, // probably some kind of breadth-first search to find a valid one foreach (var node in endNode.GetNeighbors()) { if (Traversable(pathfindingArgs.CollisionMask, pathfindingArgs.Access, node)) { endNode = node; return(true); } } } return(false); } return(true); }
public static bool DirectionTraversable(int collisionMask, ICollection <string> access, PathfindingNode currentNode, Direction direction) { // If it's a diagonal we need to check NSEW to see if we can get to it and stop corner cutting, NE needs N and E etc. // Given there's different collision layers stored for each node in the graph it's probably not worth it to cache this // Also this will help with corner-cutting PathfindingNode northNeighbor = null; PathfindingNode southNeighbor = null; PathfindingNode eastNeighbor = null; PathfindingNode westNeighbor = null; foreach (var neighbor in currentNode.GetNeighbors()) { if (neighbor.TileRef.X == currentNode.TileRef.X && neighbor.TileRef.Y == currentNode.TileRef.Y + 1) { northNeighbor = neighbor; continue; } if (neighbor.TileRef.X == currentNode.TileRef.X + 1 && neighbor.TileRef.Y == currentNode.TileRef.Y) { eastNeighbor = neighbor; continue; } if (neighbor.TileRef.X == currentNode.TileRef.X && neighbor.TileRef.Y == currentNode.TileRef.Y - 1) { southNeighbor = neighbor; continue; } if (neighbor.TileRef.X == currentNode.TileRef.X - 1 && neighbor.TileRef.Y == currentNode.TileRef.Y) { westNeighbor = neighbor; continue; } } switch (direction) { case Direction.NorthEast: if (northNeighbor == null || eastNeighbor == null) { return(false); } if (!Traversable(collisionMask, access, northNeighbor) || !Traversable(collisionMask, access, eastNeighbor)) { return(false); } break; case Direction.NorthWest: if (northNeighbor == null || westNeighbor == null) { return(false); } if (!Traversable(collisionMask, access, northNeighbor) || !Traversable(collisionMask, access, westNeighbor)) { return(false); } break; case Direction.SouthWest: if (southNeighbor == null || westNeighbor == null) { return(false); } if (!Traversable(collisionMask, access, southNeighbor) || !Traversable(collisionMask, access, westNeighbor)) { return(false); } break; case Direction.SouthEast: if (southNeighbor == null || eastNeighbor == null) { return(false); } if (!Traversable(collisionMask, access, southNeighbor) || !Traversable(collisionMask, access, eastNeighbor)) { return(false); } break; } return(true); }