/** * BiomeMusicSystem.js * Cross-fade background music based on biome transitions */ class BiomeMusicSystem { constructor(scene) { this.scene = scene; // Music tracks by biome this.biomeTracks = { 'grassland': 'music/farm_ambient', 'forest': 'music/forest_ambient', 'town': 'music/town_theme', 'combat': 'music/combat_theme', 'night': 'music/night_theme' }; // Current playing track this.currentTrack = null; this.currentBiome = null; // Cross-fade settings this.fadeDuration = 2000; // 2 seconds this.volume = 0.5; // Master volume console.log('🎵 BiomeMusicSystem initialized'); } /** * Preload all music tracks */ preload() { Object.entries(this.biomeTracks).forEach(([biome, track]) => { if (this.scene.cache.audio.exists(track)) { console.log(`✅ Music ready: ${track}`); } else { console.warn(`⚠️ Music missing: ${track}`); } }); } /** * Start music for a biome */ playBiomeMusic(biome) { // Skip if already playing this biome's music if (biome === this.currentBiome && this.currentTrack) { return; } const trackKey = this.biomeTracks[biome]; if (!trackKey) { console.warn(`⚠️ No music for biome: ${biome}`); return; } // Check if track exists if (!this.scene.cache.audio.exists(trackKey)) { console.warn(`⚠️ Music not loaded: ${trackKey}`); return; } console.log(`🎵 Transitioning to: ${biome} (${trackKey})`); // Cross-fade to new track this.crossFadeTo(trackKey, biome); } /** * Cross-fade from current track to new track */ crossFadeTo(newTrackKey, biome) { const oldTrack = this.currentTrack; // Create new track const newTrack = this.scene.sound.add(newTrackKey, { loop: true, volume: 0 // Start silent }); newTrack.play(); // Fade in new track this.scene.tweens.add({ targets: newTrack, volume: this.volume, duration: this.fadeDuration, ease: 'Linear' }); // Fade out old track if it exists if (oldTrack) { this.scene.tweens.add({ targets: oldTrack, volume: 0, duration: this.fadeDuration, ease: 'Linear', onComplete: () => { oldTrack.stop(); oldTrack.destroy(); } }); } // Update current track this.currentTrack = newTrack; this.currentBiome = biome; } /** * Stop all music */ stop() { if (this.currentTrack) { this.scene.tweens.add({ targets: this.currentTrack, volume: 0, duration: 1000, ease: 'Linear', onComplete: () => { this.currentTrack.stop(); this.currentTrack.destroy(); this.currentTrack = null; this.currentBiome = null; } }); } } /** * Set master volume */ setVolume(volume) { this.volume = Phaser.Math.Clamp(volume, 0, 1); if (this.currentTrack) { this.currentTrack.setVolume(this.volume); } } /** * Update called every frame * Checks player's current biome and switches music */ update(playerX, playerY) { // Get current biome from biomeSystem if (!this.scene.biomeSystem) return; const gridX = Math.floor(playerX / 48); const gridY = Math.floor(playerY / 48); const biome = this.scene.biomeSystem.getBiomeAt(gridX, gridY); if (biome && biome !== this.currentBiome) { this.playBiomeMusic(biome); } // Handle night music override if (this.scene.timeSystem) { const hour = this.scene.timeSystem.currentHour || 12; if (hour >= 20 || hour < 6) { // Night time if (this.currentBiome !== 'night') { this.playBiomeMusic('night'); } } } } }