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)); } } } }, // Draw fog of war effect draw(ctx) { // Draw fog over unrevealed areas HexGrid.getViewportHexes().forEach(hex => { if (!this.isRevealed(hex) || !this.isVisible(hex)) { const pixel = HexGrid.toPixel(hex); const screenX = pixel.x - Camera.x; const screenY = pixel.y - Camera.y; ctx.fillStyle = this.isRevealed(hex) ? 'rgba(0, 0, 0, 0.5)' : // Darker fog for unexplored areas 'rgba(0, 0, 0, 0.8)'; // Lighter fog for explored but not visible // Draw fog hex ctx.beginPath(); for (let i = 0; i < 6; i++) { const angle = 2 * Math.PI / 6 * i; const xPos = screenX + HexGrid.SIZE * Math.cos(angle); const yPos = screenY + HexGrid.SIZE * Math.sin(angle); if (i === 0) { ctx.moveTo(xPos, yPos); } else { ctx.lineTo(xPos, yPos); } } ctx.closePath(); ctx.fill(); } }); } };