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(); } } }); } };