Repository navigation
Path Manipulation
The raw output of an A* algorithm is mathematically correct, but aesthetically "meh". It consists of grid coordinates (integers), meaning your entities will move in zig-zag lines and stand exactly in the corner of blocks.
PathUtils is your cosmetic surgeon. It takes a raw path and makes it smooth, centered, or compressed.
[!NOTE] All methods in PathUtils are immutable. They do not modify the original path; they return a new, better one.
A* thinks in blocks. Real movement happens in curves. interpolate adds intermediate points between the grid nodes. Use this if you render movement client-side and want to avoid the "robot walk" effect.
Path rawPath = result.getPath();
// Insert points so that no two steps are further than 0.5 units apart.
// Turns a 10-step path into a 50-step smooth curve.
Path smoothPath = PathUtils.interpolate(rawPath, 0.5);Sometimes you have too much data. If you are sending paths over the network, you don't need every single step on a straight line. simplify throws away points based on an epsilon (sampling density).
// Keep only ~10% of the points (epsilon = 0.1)
// Useful for minimaps or low-bandwidth updates.
Path lightPath = PathUtils.simplify(rawPath, 0.1);This is the most critical feature for Minecraft/Voxel games. A* returns block coordinates like (1, 64, 1). If you teleport a zombie there, it stands in the corner of the block. You usually want (1.5, 64, 1.5).
mutatePositions lets you apply a function to every point.
// "Centering" the path
Path centerPath = PathUtils.mutatePositions(rawPath, pos -> {
return new PathPosition(
pos.getX() + 0.5,
pos.getY(), // Don't change Y (unless you want them floating)
pos.getZ() + 0.5
);
});Sometimes you need to stitch paths together or cut them short.
-
join(pathA, pathB): Glues two paths together.
-
trim(path, maxLength): Cuts the path off after N steps. Useful if the target is moving and you only want to walk the first few steps before recalculating.
// Walk the first 10 steps, then recalculate
Path shortPath = PathUtils.trim(longPath, 10);