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.
|
- 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.
|
- **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).
|
- **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
|
### 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.
|
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;
|
const maxSteps = Math.abs(endX - currentX) + Math.abs(endY - currentY) + 20;
|
||||||
|
|
||||||
|
let prevX = null;
|
||||||
|
let prevY = null;
|
||||||
|
|
||||||
for (let i = 0; i < maxSteps; i++) {
|
for (let i = 0; i < maxSteps; i++) {
|
||||||
path.push({ x: currentX, y: currentY });
|
path.push({ x: currentX, y: currentY });
|
||||||
|
|
||||||
@@ -816,10 +819,20 @@ export class GameEngine {
|
|||||||
const isEnd = (currentX === target.x && currentY === target.y);
|
const isEnd = (currentX === target.x && currentY === target.y);
|
||||||
|
|
||||||
if (!isStart && !isEnd) {
|
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;
|
blocked = true;
|
||||||
blocker = { type: 'wall', x: currentX, y: currentY };
|
blocker = { type: 'wall', x: currentX, y: currentY };
|
||||||
console.log(`[LOS] Blocked by WALL at ${currentX},${currentY}`);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -872,27 +885,31 @@ export class GameEngine {
|
|||||||
const cornerCrossing = Math.abs(tMaxX - tMaxY) < CORNER_EPSILON;
|
const cornerCrossing = Math.abs(tMaxX - tMaxY) < CORNER_EPSILON;
|
||||||
|
|
||||||
if (cornerCrossing) {
|
if (cornerCrossing) {
|
||||||
// Check both orthogonal neighbors
|
// Check connectivity to both orthogonal neighbors
|
||||||
const neighborX = currentX + stepX;
|
const neighborX = currentX + stepX;
|
||||||
const neighborY = currentY + stepY;
|
const neighborY = currentY + stepY;
|
||||||
|
|
||||||
// Check horizontal neighbor
|
// Check horizontal neighbor connectivity
|
||||||
if (this.dungeon.grid.isWall(neighborX, currentY)) {
|
if (!this.dungeon.grid.canMoveBetween(currentX, currentY, neighborX, currentY)) {
|
||||||
blocked = true;
|
blocked = true;
|
||||||
blocker = { type: 'wall', x: neighborX, y: currentY };
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check vertical neighbor
|
// Check vertical neighbor connectivity
|
||||||
if (this.dungeon.grid.isWall(currentX, neighborY)) {
|
if (!this.dungeon.grid.canMoveBetween(currentX, currentY, currentX, neighborY)) {
|
||||||
blocked = true;
|
blocked = true;
|
||||||
blocker = { type: 'wall', x: currentX, y: neighborY };
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update Previous
|
||||||
|
prevX = currentX;
|
||||||
|
prevY = currentY;
|
||||||
|
|
||||||
if (tMaxX < tMaxY) {
|
if (tMaxX < tMaxY) {
|
||||||
tMaxX += tDeltaX;
|
tMaxX += tDeltaX;
|
||||||
currentX += stepX;
|
currentX += stepX;
|
||||||
|
|||||||
Reference in New Issue
Block a user