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.rainParticles = []; // {x, y, speed, length} // --- 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) { if (this.currentWeather === 'rain' || this.currentWeather === 'storm') { const width = this.scene.scale.width; const height = this.scene.scale.height; for (const drop of this.rainParticles) { drop.y += (drop.speed * delta) / 1000; // Wrap around if (drop.y > height) { drop.y = -10; drop.x = Math.random() * width; } } } } 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); // Draw drops overlay.lineStyle(1, 0x88aaff, 0.5); for (const drop of this.rainParticles) { overlay.beginPath(); overlay.moveTo(drop.x, drop.y); overlay.lineTo(drop.x - 2, drop.y + drop.length); overlay.strokePath(); } } } 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 width = this.scene.scale.width; const height = this.scene.scale.height; const dropCount = heavy ? 150 : 100; for (let i = 0; i < dropCount; i++) { this.rainParticles.push({ x: Math.random() * width, y: Math.random() * height, speed: heavy ? Phaser.Math.Between(400, 600) : Phaser.Math.Between(200, 400), length: heavy ? Phaser.Math.Between(10, 15) : Phaser.Math.Between(5, 10) }); } } clearWeather() { this.rainParticles = []; } // --- 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; } }