fix: Refine LOS wall detection to use connectivity rules (canMoveBetween)

This commit is contained in:
2026-01-06 22:30:01 +01:00
parent 61c7cc3313
commit 377096c530
2 changed files with 27 additions and 9 deletions

View File

@@ -17,6 +17,7 @@
- Implementado algoritmo estricto (Amanatides & Woo) para evitar tiros a través de muros.
- **Tolerancia de Rozamiento**: Añadido margen (hitbox 0.4) para permitir tiros que rozan el borde de una casilla de entidad.
- **Corrección de "Diagonal Leaking"**: Solucionado el problema donde los disparos atravesaban esquinas diagonales entre muros (se verifican ambos vecinos en cruces de vértice).
- **Detección de Muros por Conectividad**: Reemplazada la comprobación simple de vacío por `canMoveBetween`, asegurando que los muros entre habitaciones/pasillos contiguos bloquen la visión correctamente si no hay puerta, incluso si ambas celdas tienen suelo.
### Estado Actual
El juego cuenta con una visualización táctica profesional y un sistema de línea de visión robusto y justo, eliminando los fallos de detección en esquinas y muros.

View File

@@ -809,6 +809,9 @@ export class GameEngine {
const maxSteps = Math.abs(endX - currentX) + Math.abs(endY - currentY) + 20;
let prevX = null;
let prevY = null;
for (let i = 0; i < maxSteps; i++) {
path.push({ x: currentX, y: currentY });
@@ -816,10 +819,20 @@ export class GameEngine {
const isEnd = (currentX === target.x && currentY === target.y);
if (!isStart && !isEnd) {
if (this.dungeon.grid.isWall(currentX, currentY)) {
// WALL CHECK: Use Connectvity (canMoveBetween)
// This detects walls between tiles even if both tiles are floor.
// It also detects VOID cells (because canMoveBetween returns false if destination is void).
if (prevX !== null) {
if (!this.dungeon.grid.canMoveBetween(prevX, prevY, currentX, currentY)) {
blocked = true;
blocker = { type: 'wall', x: currentX, y: currentY };
console.log(`[LOS] Blocked by WALL/BORDER between ${prevX},${prevY} and ${currentX},${currentY}`);
break;
}
} else if (this.dungeon.grid.isWall(currentX, currentY)) {
// Fallback for start/isolated case (should rarely happen for LOS path)
blocked = true;
blocker = { type: 'wall', x: currentX, y: currentY };
console.log(`[LOS] Blocked by WALL at ${currentX},${currentY}`);
break;
}
@@ -872,27 +885,31 @@ export class GameEngine {
const cornerCrossing = Math.abs(tMaxX - tMaxY) < CORNER_EPSILON;
if (cornerCrossing) {
// Check both orthogonal neighbors
// Check connectivity to both orthogonal neighbors
const neighborX = currentX + stepX;
const neighborY = currentY + stepY;
// Check horizontal neighbor
if (this.dungeon.grid.isWall(neighborX, currentY)) {
// Check horizontal neighbor connectivity
if (!this.dungeon.grid.canMoveBetween(currentX, currentY, neighborX, currentY)) {
blocked = true;
blocker = { type: 'wall', x: neighborX, y: currentY };
console.log(`[LOS] Blocked by CORNER WALL at ${neighborX},${currentY}`);
console.log(`[LOS] Blocked by CORNER WALL (H) at ${neighborX},${currentY}`);
break;
}
// Check vertical neighbor
if (this.dungeon.grid.isWall(currentX, neighborY)) {
// Check vertical neighbor connectivity
if (!this.dungeon.grid.canMoveBetween(currentX, currentY, currentX, neighborY)) {
blocked = true;
blocker = { type: 'wall', x: currentX, y: neighborY };
console.log(`[LOS] Blocked by CORNER WALL at ${currentX},${neighborY}`);
console.log(`[LOS] Blocked by CORNER WALL (V) at ${currentX},${neighborY}`);
break;
}
}
// Update Previous
prevX = currentX;
prevY = currentY;
if (tMaxX < tMaxY) {
tMaxX += tDeltaX;
currentX += stepX;