From 377096c53090b6af0d5e101da8b13957ae0e4bfb Mon Sep 17 00:00:00 2001 From: Marti Vich Date: Tue, 6 Jan 2026 22:30:01 +0100 Subject: [PATCH] fix: Refine LOS wall detection to use connectivity rules (canMoveBetween) --- DEVLOG.md | 1 + src/engine/game/GameEngine.js | 35 ++++++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/DEVLOG.md b/DEVLOG.md index e5dbe62..7abc466 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -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. diff --git a/src/engine/game/GameEngine.js b/src/engine/game/GameEngine.js index f1ae16b..f33bd20 100644 --- a/src/engine/game/GameEngine.js +++ b/src/engine/game/GameEngine.js @@ -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;