fix: Refine LOS wall detection to use connectivity rules (canMoveBetween)
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user