raycastGrid static method

RaycastGridHit? raycastGrid(
  1. Ray ray, {
  2. required int cellSize,
  3. required double maxDistance,
  4. required bool isSolid(
    1. int tx,
    2. int ty
    ),
})

Implementation

static RaycastGridHit? raycastGrid(
  Ray ray, {
  required int cellSize,
  required double maxDistance,
  required bool Function(int tx, int ty) isSolid,
}) {
  final dirX = ray.direction.x;
  final dirY = ray.direction.y;

  final startX = ray.origin.x / cellSize;
  final startY = ray.origin.y / cellSize;

  final stepSizeX = dirX.abs() < 1e-10 ? double.infinity : 1 / dirX.abs();
  final stepSizeY = dirY.abs() < 1e-10 ? double.infinity : 1 / dirY.abs();

  int mapX = startX.floor();
  int mapY = startY.floor();

  double rayLenX, rayLenY;
  int stepX, stepY;

  if (dirX < 0) {
    stepX = -1;
    rayLenX = (startX - mapX) * stepSizeX;
  } else {
    stepX = 1;
    rayLenX = ((mapX + 1) - startX) * stepSizeX;
  }

  if (dirY < 0) {
    stepY = -1;
    rayLenY = (startY - mapY) * stepSizeY;
  } else {
    stepY = 1;
    rayLenY = ((mapY + 1) - startY) * stepSizeY;
  }

  double distance = 0;
  var hitVertical = false;

  while (distance < maxDistance) {
    if (rayLenX < rayLenY) {
      mapX += stepX;
      distance = rayLenX;
      rayLenX += stepSizeX;
      hitVertical = true;
    } else {
      mapY += stepY;
      distance = rayLenY;
      rayLenY += stepSizeY;
      hitVertical = false;
    }

    if (distance >= maxDistance) break;

    if (isSolid(mapX, mapY)) {
      return RaycastGridHit(
        tx: mapX,
        ty: mapY,
        distance: distance * cellSize,
        point: Vec2(
          ray.origin.x + dirX * distance * cellSize,
          ray.origin.y + dirY * distance * cellSize,
        ),
        normalX: hitVertical ? -stepX : 0,
        normalY: hitVertical ? 0 : -stepY,
      );
    }
  }

  return null;
}