1
0

SharedPathfindingSystem.Line.cs 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. namespace Content.Shared.NPC;
  2. public abstract partial class SharedPathfindingSystem
  3. {
  4. public static void GridCast(Vector2i start, Vector2i end, Vector2iCallback callback)
  5. {
  6. // https://gist.github.com/Pyr3z/46884d67641094d6cf353358566db566
  7. // declare all locals at the top so it's obvious how big the footprint is
  8. int dx, dy, xinc, yinc, side, i, error;
  9. // starting cell is always returned
  10. if (!callback(start))
  11. return;
  12. xinc = (end.X < start.X) ? -1 : 1;
  13. yinc = (end.Y < start.Y) ? -1 : 1;
  14. dx = xinc * (end.X - start.X);
  15. dy = yinc * (end.Y - start.Y);
  16. var ax = start.X;
  17. var ay = start.Y;
  18. if (dx == dy) // Handle perfect diagonals
  19. {
  20. // I include this "optimization" for more aesthetic reasons, actually.
  21. // While Bresenham's Line can handle perfect diagonals just fine, it adds
  22. // additional cells to the line that make it not a perfect diagonal
  23. // anymore. So, while this branch is ~twice as fast as the next branch,
  24. // the real reason it is here is for style.
  25. // Also, there *is* the reason of performance. If used for cell-based
  26. // raycasts, for example, then perfect diagonals will check half as many
  27. // cells.
  28. while (dx --> 0)
  29. {
  30. ax += xinc;
  31. ay += yinc;
  32. if (!callback(new Vector2i(ax, ay)))
  33. return;
  34. }
  35. return;
  36. }
  37. // Handle all other lines
  38. side = -1 * ((dx == 0 ? yinc : xinc) - 1);
  39. i = dx + dy;
  40. error = dx - dy;
  41. dx *= 2;
  42. dy *= 2;
  43. while (i --> 0)
  44. {
  45. if (error > 0 || error == side)
  46. {
  47. ax += xinc;
  48. error -= dy;
  49. }
  50. else
  51. {
  52. ay += yinc;
  53. error += dx;
  54. }
  55. if (!callback(new Vector2i(ax, ay)))
  56. return;
  57. }
  58. }
  59. public delegate bool Vector2iCallback(Vector2i index);
  60. }