| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- namespace Content.Shared.NPC;
- public abstract partial class SharedPathfindingSystem
- {
- public static void GridCast(Vector2i start, Vector2i end, Vector2iCallback callback)
- {
- // https://gist.github.com/Pyr3z/46884d67641094d6cf353358566db566
- // declare all locals at the top so it's obvious how big the footprint is
- int dx, dy, xinc, yinc, side, i, error;
- // starting cell is always returned
- if (!callback(start))
- return;
- xinc = (end.X < start.X) ? -1 : 1;
- yinc = (end.Y < start.Y) ? -1 : 1;
- dx = xinc * (end.X - start.X);
- dy = yinc * (end.Y - start.Y);
- var ax = start.X;
- var ay = start.Y;
- if (dx == dy) // Handle perfect diagonals
- {
- // I include this "optimization" for more aesthetic reasons, actually.
- // While Bresenham's Line can handle perfect diagonals just fine, it adds
- // additional cells to the line that make it not a perfect diagonal
- // anymore. So, while this branch is ~twice as fast as the next branch,
- // the real reason it is here is for style.
- // Also, there *is* the reason of performance. If used for cell-based
- // raycasts, for example, then perfect diagonals will check half as many
- // cells.
- while (dx --> 0)
- {
- ax += xinc;
- ay += yinc;
- if (!callback(new Vector2i(ax, ay)))
- return;
- }
- return;
- }
- // Handle all other lines
- side = -1 * ((dx == 0 ? yinc : xinc) - 1);
- i = dx + dy;
- error = dx - dy;
- dx *= 2;
- dy *= 2;
- while (i --> 0)
- {
- if (error > 0 || error == side)
- {
- ax += xinc;
- error -= dy;
- }
- else
- {
- ay += yinc;
- error += dx;
- }
- if (!callback(new Vector2i(ax, ay)))
- return;
- }
- }
- public delegate bool Vector2iCallback(Vector2i index);
- }
|