Skip to content

Commit

Permalink
Properly detect clipping with neighboring tiles instead of blindly di…
Browse files Browse the repository at this point in the history
…sallowing coast tiles

This improves waypoint count by quiet a lot
  • Loading branch information
platz1de committed Oct 3, 2024
1 parent bfb8562 commit 3a46491
Showing 1 changed file with 36 additions and 3 deletions.
39 changes: 36 additions & 3 deletions src/util/VoxelRayTrace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function rayTraceWater(x: number, y: number, dx: number, dy: number): num

/**
* Checks if there is a line of sight between two points.
* This function does only allow passing through tiles which aren't directly adjacent to territory tiles.
* This function requires a distance of half a tile to non-water tiles.
* @param x1 The x coordinate of the starting point
* @param y1 The y coordinate of the starting point
* @param x2 The x coordinate of the ending point
Expand All @@ -49,15 +49,48 @@ export function checkLineOfSight(x1: number, y1: number, x2: number, y2: number)
const steps = Math.max(Math.abs(dx), Math.abs(dy));
const stepX = dx / steps;
const stepY = dy / steps;
const minDistance = stepX === 0 || stepY === 0 ? 0 : -1; // Prevent clipping through corners
let x = x1 + 0.5; // We start at the center of the first tile
let y = y1 + 0.5;
if (gameMap.getDistance(x1 + y1 * gameMap.width) === -1 && !checkCoastDistance(x, y, stepX, stepY)) {
return false;
}
if (gameMap.getDistance(x2 + y2 * gameMap.width) === -1 && !checkCoastDistance(x2 + 0.5, y2 + 0.5, -stepX, -stepY)) {
return false;
}
for (let i = 1; i < steps; i++) {
x += stepX;
y += stepY;
if (gameMap.getDistance(Math.floor(x) + Math.floor(y) * gameMap.width) >= minDistance) {
const distance = gameMap.getDistance(Math.floor(x) + Math.floor(y) * gameMap.width);
if (distance >= 0) {
return false;
}
// Prevent clipping through corners
if (distance === -1) {
if (dx === 0 || dy === 0) continue;
if (!checkCoastDistance(x, y, stepX, stepY) || !checkCoastDistance(x, y, -stepX, -stepY)) { //Check this and next step
return false;
}
}
}
return true;
}

/**
* Checks whether the given step is allowed from the given tile.
* This function disallows passing closer than half a tile to non-water tiles.
* @param x The x coordinate of the tile
* @param y The y coordinate of the tile
* @param stepX The x direction of the step
* @param stepY The y direction of the step
* @internal
*/
function checkCoastDistance(x: number, y: number, stepX: number, stepY: number): boolean {
if (Math.abs(stepX) > Math.abs(stepY)) {
if (gameMap.getDistance(Math.floor(x) + Math.floor(y + stepY - 0.49) * gameMap.width) >= 0) return false;
if (gameMap.getDistance(Math.floor(x) + Math.floor(y + stepY + 0.49) * gameMap.width) >= 0) return false;
} else {
if (gameMap.getDistance(Math.floor(x + stepX - 0.49) + Math.floor(y) * gameMap.width) >= 0) return false;
if (gameMap.getDistance(Math.floor(x + stepX + 0.49) + Math.floor(y) * gameMap.width) >= 0) return false;
}
return true;
}

0 comments on commit 3a46491

Please sign in to comment.