class WeatherSystem { constructor(scene) { this.scene = scene; // --- Time Configuration --- this.fullDaySeconds = 300; // 5 minutes = 24 game hours this.gameTime = 8; // Start at 8:00 this.dayCount = 1; // --- Weather Configuration --- this.currentWeather = 'clear'; this.weatherDuration = 0; this.maxWeatherDuration = 10000; // Random duration logic handles this this.rainEmitter = null; // Replaced manual Array with Emitter // --- State --- this.currentPhase = 'day'; this.init(); } init() { // Start weather cycle this.changeWeather(); } getOverlay() { const uiScene = this.scene.scene.get('UIScene'); if (uiScene && uiScene.overlayGraphics) { return uiScene.overlayGraphics; } return null; } update(delta) { // 1. Update Time this.updateTime(delta); // 2. Update Weather Logic (Durations, Changes) this.updateWeatherLogic(delta); // 3. Update Physics (Rain drops) this.updateWeatherPhysics(delta); // 4. Render Atmosphere (Time + Weather) this.render(); } updateTime(delta) { const seconds = delta / 1000; const gameHoursPerRealSecond = 24 / this.fullDaySeconds; this.gameTime += seconds * gameHoursPerRealSecond; if (this.gameTime >= 24) { this.gameTime -= 24; this.dayCount++; console.log(`🌞 Day ${this.dayCount} started!`); } // Update Phase const phase = this.getPhase(this.gameTime); if (phase !== this.currentPhase) { this.currentPhase = phase; console.log(`🌅 Time of Day: ${phase} (${Math.floor(this.gameTime)}:00)`); } // Update UI Clock const uiScene = this.scene.scene.get('UIScene'); if (uiScene && uiScene.clockText) { const hours = Math.floor(this.gameTime); const minutes = Math.floor((this.gameTime - hours) * 60); const timeString = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`; uiScene.clockText.setText(`Day ${this.dayCount} - ${timeString}`); } } getPhase(hour) { if (hour >= 5 && hour < 7) return 'dawn'; if (hour >= 7 && hour < 18) return 'day'; if (hour >= 18 && hour < 20) return 'dusk'; return 'night'; } updateWeatherLogic(delta) { this.weatherDuration += delta; if (this.weatherDuration > this.maxWeatherDuration) { this.changeWeather(); } } updateWeatherPhysics(delta) { // Optimisation: Physics now handled by Phaser Particles } render() { const overlay = this.getOverlay(); if (!overlay) return; // IMPORTANT: Clear previous frame to avoid buildup overlay.clear(); const width = this.scene.scale.width; const height = this.scene.scale.height; // --- LAYER 1: Day/Night Cycle --- this.renderDayNight(overlay, width, height); // --- LAYER 2: Weather Effects (Fog, Rain darkness) --- this.renderWeatherEffects(overlay, width, height); } renderDayNight(overlay, width, height) { const hour = this.gameTime; let color = 0x000033; // Default night let alpha = 0; if (hour >= 0 && hour < 5) { // Deep Night color = 0x000033; alpha = 0.6; } else if (hour >= 5 && hour < 7) { // Dawn color = 0xFF6B35; const progress = (hour - 5) / 2; alpha = 0.6 - (progress * 0.6); } else if (hour >= 7 && hour < 18) { // Day alpha = 0; } else if (hour >= 18 && hour < 20) { // Dusk color = 0x8B4789; const progress = (hour - 18) / 2; alpha = progress * 0.5; } else if (hour >= 20 && hour < 24) { // Night color = 0x000033; const progress = (hour - 20) / 4; alpha = 0.5 + (progress * 0.1); } if (alpha > 0) { overlay.fillStyle(color, alpha); overlay.fillRect(0, 0, width, height); } } renderWeatherEffects(overlay, width, height) { // Fog if (this.currentWeather === 'fog') { overlay.fillStyle(0xcccccc, 0.4); overlay.fillRect(0, 0, width, height); } // Rain / Storm if (this.currentWeather === 'rain' || this.currentWeather === 'storm') { const isDark = this.currentWeather === 'storm' ? 0.3 : 0.2; // Additive darkness for storm overlay.fillStyle(0x000033, isDark); overlay.fillRect(0, 0, width, height); // Rain drops are now particles (separate GameObject) } } changeWeather() { this.clearWeather(); const rand = Math.random(); if (rand < 0.6) { this.currentWeather = 'clear'; this.maxWeatherDuration = Phaser.Math.Between(10000, 30000); } else if (rand < 0.8) { this.currentWeather = 'rain'; this.startRain(false); this.maxWeatherDuration = Phaser.Math.Between(10000, 20000); } else if (rand < 0.9) { this.currentWeather = 'storm'; this.startRain(true); this.maxWeatherDuration = Phaser.Math.Between(8000, 15000); } else { this.currentWeather = 'fog'; this.maxWeatherDuration = Phaser.Math.Between(10000, 20000); } this.weatherDuration = 0; console.log(`Weather changed to: ${this.currentWeather}`); } startRain(heavy) { const uiScene = this.scene.scene.get('UIScene'); if (!uiScene) return; // Check Settings const quality = this.scene.settings ? this.scene.settings.particles : 'HIGH'; if (quality === 'NONE') return; // Ensure texture exists if (!this.scene.textures.exists('rain_drop')) { const graphics = this.scene.make.graphics({ x: 0, y: 0, add: false }); graphics.fillStyle(0x88aaff, 1); graphics.fillRect(0, 0, 2, 8); graphics.generateTexture('rain_drop', 2, 8); graphics.destroy(); } // Clean up old if (this.rainEmitter) { this.rainEmitter.destroy(); } const width = this.scene.scale.width; let pQuantity = heavy ? 5 : 2; let pFreq = heavy ? 10 : 30; if (quality === 'LOW') { pQuantity = heavy ? 2 : 1; pFreq = heavy ? 50 : 100; } // Use modern particles or fallback // Helper to support both if needed, but standard 3.60+ is: this.rainEmitter = uiScene.add.particles(0, 0, 'rain_drop', { x: { min: 0, max: width }, y: -20, quantity: pQuantity, frequency: pFreq, // Emit every X ms lifespan: 1500, speedY: { min: heavy ? 600 : 400, max: heavy ? 900 : 600 }, speedX: { min: -50, max: 0 }, // Slight wind scaleY: { min: 1.0, max: 2.0 }, alpha: { start: 0.6, end: 0 }, emitting: true }); // Depth just above overlay (-1000) this.rainEmitter.setDepth(-990); } clearWeather() { if (this.rainEmitter) { this.rainEmitter.destroy(); this.rainEmitter = null; } } // --- Getters for Other Systems --- getCurrentHour() { return Math.floor(this.gameTime); } getDayCount() { return this.dayCount; } isNight() { const hour = this.gameTime; return hour >= 20 || hour < 5; } isDay() { const hour = this.gameTime; return hour >= 7 && hour < 18; } }