const FogOfWar = {
// Set of revealed hex coordinates (as strings)
revealed: new Set(),
// Configuration
VISION_RANGE: Config.player.VISION_RANGE,
init() {
this.revealed.clear();
this.updateVisibility(player.position);
},
// Convert hex to string key for Set storage
hexToKey(hex) {
return `${hex.q},${hex.r}`;
},
// Check if a hex is currently visible
isVisible(hex) {
const playerPos = player.getCurrentPosition();
const distance = this.getHexDistance(hex, playerPos);
return distance <= this.VISION_RANGE;
},
// Check if a hex has been revealed
isRevealed(hex) {
return this.revealed.has(this.hexToKey(hex));
},
// Calculate distance between two hexes
getHexDistance(a, b) {
return Math.max(
Math.abs(a.q - b.q),
Math.abs(a.r - b.r),
Math.abs((a.q + a.r) - (b.q + b.r))
);
},
// Update visibility based on player position
updateVisibility(center) {
// Get all hexes within vision range
for (let q = -this.VISION_RANGE; q <= this.VISION_RANGE; q++) {
for (let r = -this.VISION_RANGE; r <= this.VISION_RANGE; r++) {
const hex = {
q: center.q + q,
r: center.r + r
};
if (this.getHexDistance(center, hex) <= this.VISION_RANGE) {
this.revealed.add(this.hexToKey(hex));
}
}
}
},
getFogState(hex) {
if (!this.isRevealed(hex)) return Config.fog.states.HIDDEN;
if (!this.isVisible(hex)) return Config.fog.states.REVEALED;
return Config.fog.states.VISIBLE;
},
// Draw fog of war effect
draw(ctx) {
HexGrid.getViewportHexes().forEach(hex => {
const fogState = this.getFogState(hex);
if (fogState.alpha > 0) {
const screen = HexGrid.toScreenCoordinates(hex, Camera);
// Draw fog fill
ctx.fillStyle = fogState === Config.fog.states.HIDDEN ?
Config.colors.FOG.HIDDEN :
Config.colors.FOG.REVEALED;
HexGrid.drawHexPath(ctx, screen.x, screen.y, HexGrid.SIZE, 1);
ctx.fill();
// Draw grid lines only for revealed but not visible hexes
if (fogState === Config.fog.states.REVEALED) {
ctx.strokeStyle = Config.colors.FOG.GRID_DIM;
ctx.lineWidth = 1;
ctx.stroke();
}
}
});
}
};