// TransitionSystem - Smooth transitions between biomes class TransitionSystem { constructor(scene, biomeSystem) { this.scene = scene; this.biomeSystem = biomeSystem; // Transition settings this.transitionWidth = 25; // Tiles for smooth transition this.blendEnabled = true; console.log('🌈 TransitionSystem initialized (width: ' + this.transitionWidth + ' tiles)'); } // Check if tile is in transition zone isInTransitionZone(x, y) { const currentBiome = this.biomeSystem.getBiomeAt(x, y); // Check nearby tiles for different biomes const radius = Math.ceil(this.transitionWidth / 2); for (let dy = -radius; dy <= radius; dy++) { for (let dx = -radius; dx <= radius; dx++) { if (dx === 0 && dy === 0) continue; const checkX = x + dx; const checkY = y + dy; const checkBiome = this.biomeSystem.getBiomeAt(checkX, checkY); if (checkBiome !== currentBiome) { return true; // Different biome nearby! } } } return false; } // Get transition blend for a tile getTransitionBlend(x, y) { if (!this.blendEnabled) { return { primaryBiome: this.biomeSystem.getBiomeAt(x, y), blendBiome: null, blendFactor: 0 }; } const currentBiome = this.biomeSystem.getBiomeAt(x, y); // Find closest different biome let closestBiome = null; let closestDistance = Infinity; const radius = this.transitionWidth; for (let dy = -radius; dy <= radius; dy++) { for (let dx = -radius; dx <= radius; dx++) { if (dx === 0 && dy === 0) continue; const checkX = x + dx; const checkY = y + dy; const checkBiome = this.biomeSystem.getBiomeAt(checkX, checkY); if (checkBiome !== currentBiome) { const distance = Math.sqrt(dx * dx + dy * dy); if (distance < closestDistance) { closestDistance = distance; closestBiome = checkBiome; } } } } if (closestBiome === null) { // No transition return { primaryBiome: currentBiome, blendBiome: null, blendFactor: 0 }; } // Calculate blend factor (0 = primary, 1 = blend) const blendFactor = Math.max(0, 1 - (closestDistance / this.transitionWidth)); return { primaryBiome: currentBiome, blendBiome: closestBiome, blendFactor: blendFactor }; } // Get blended tile color getBlendedTileColor(x, y) { const blend = this.getTransitionBlend(x, y); if (blend.blendFactor === 0 || !blend.blendBiome) { // No blending, return primary biome color return this.getBiomeColor(blend.primaryBiome); } // Blend colors const color1 = this.getBiomeColor(blend.primaryBiome); const color2 = this.getBiomeColor(blend.blendBiome); return this.blendColors(color1, color2, blend.blendFactor); } // Get biome base color getBiomeColor(biomeId) { const colors = { 'grassland': 0x3CB371, // Green 'forest': 0x2d5016, // Dark green 'desert': 0xd4c4a1, // Sand 'mountain': 0x808080, // Gray 'swamp': 0x3d5a3d // Murky green }; return colors[biomeId] || 0x3CB371; } // Blend two colors blendColors(color1, color2, factor) { // Extract RGB components const r1 = (color1 >> 16) & 0xFF; const g1 = (color1 >> 8) & 0xFF; const b1 = color1 & 0xFF; const r2 = (color2 >> 16) & 0xFF; const g2 = (color2 >> 8) & 0xFF; const b2 = color2 & 0xFF; // Blend const r = Math.round(r1 * (1 - factor) + r2 * factor); const g = Math.round(g1 * (1 - factor) + g2 * factor); const b = Math.round(b1 * (1 - factor) + b2 * factor); // Combine back to hex return (r << 16) | (g << 8) | b; } // Get mixed features for transition zones getMixedFeatures(x, y) { const blend = this.getTransitionBlend(x, y); if (blend.blendFactor === 0 || !blend.blendBiome) { // No transition, use primary biome features only return this.biomeSystem.applyBiomeFeatures(x, y); } // Get features from both biomes const primaryFeatures = this.getBiomeFeatures(blend.primaryBiome, x, y); const blendFeatures = this.getBiomeFeatures(blend.blendBiome, x, y); // Mix based on blend factor const mixedFeatures = []; // Randomly choose which biome's features to use based on blend factor if (Math.random() > blend.blendFactor) { // Use primary biome features if (primaryFeatures.length > 0 && Math.random() < 0.5) { // Reduce density in transitions mixedFeatures.push(...primaryFeatures); } } else { // Use blend biome features if (blendFeatures.length > 0 && Math.random() < 0.5) { mixedFeatures.push(...blendFeatures); } } return mixedFeatures; } // Get features for a specific biome getBiomeFeatures(biomeId, x, y) { // Temporarily set biome to get its features const originalBiome = this.biomeSystem.getBiomeAt(x, y); // This is a bit hacky - we'd need to refactor BiomeSystem to support this better // For now, just return features based on biome type const features = []; const biomeData = this.biomeSystem.biomes[biomeId]; if (!biomeData) return features; // Check spawn probability if (Math.random() < biomeData.spawnProbability.trees) { features.push({ type: 'tree', size: 'medium' }); } if (Math.random() < biomeData.spawnProbability.rocks) { features.push({ type: 'rock', size: 'small' }); } return features; } // Get statistics getStats() { return { transitionWidth: this.transitionWidth, blendEnabled: this.blendEnabled, biomeCount: Object.keys(this.biomeSystem.biomes).length }; } // Enable/disable transitions setBlendEnabled(enabled) { this.blendEnabled = enabled; console.log('🌈 Blend transitions: ' + (enabled ? 'ENABLED' : 'DISABLED')); } // Set transition width setTransitionWidth(width) { this.transitionWidth = Math.max(5, Math.min(50, width)); console.log('🌈 Transition width set to: ' + this.transitionWidth); } }