/** * BUILDING VISUALS & GENETICS SYSTEM * Advanced animations for farm automation buildings and genetics lab */ class BuildingVisualsSystem { constructor(scene) { this.scene = scene; this.enabled = true; // Building animations this.buildings = new Map(); this.conveyorBelts = []; this.windmills = []; this.silos = []; // Genetics lab this.geneticsLab = null; this.dnaHelixAnimation = null; this.mutationVats = []; // Settings this.settings = { buildingAnimations: true, particleEffects: true, geneticsUI: true, animationSpeed: 1.0 }; this.loadSettings(); this.init(); console.log('✅ Building Visuals System initialized'); } init() { console.log('🏭 Building animations ready'); } // ========== AUTO-PLANTER ========== createAutoPlanter(x, y) { if (!this.settings.buildingAnimations) return null; const planter = { x, y, arm: null, seed: null, isPlanting: false }; // Create mechanical arm const arm = this.scene.add.graphics(); arm.lineStyle(4, 0x888888, 1); arm.lineBetween(0, 0, 0, 30); // Vertical arm arm.lineBetween(0, 30, 20, 30); // Horizontal extension arm.setPosition(x, y); arm.setDepth(100); planter.arm = arm; this.buildings.set(`planter_${x}_${y}`, planter); return planter; } animatePlanting(planter, targetX, targetY) { if (!planter || planter.isPlanting) return; planter.isPlanting = true; // Arm extends down this.scene.tweens.add({ targets: planter.arm, y: planter.y + 20, duration: 500, ease: 'Power2', onComplete: () => { // Drop seed this.createSeedParticle(targetX, targetY); // Arm retracts this.scene.tweens.add({ targets: planter.arm, y: planter.y, duration: 500, ease: 'Power2', onComplete: () => { planter.isPlanting = false; } }); } }); } createSeedParticle(x, y) { const seed = this.scene.add.circle(x, y - 20, 3, 0x8B4513); seed.setDepth(99); this.scene.tweens.add({ targets: seed, y: y, duration: 300, ease: 'Bounce.easeOut', onComplete: () => { // Puff of dirt if (this.scene.visualEnhancements) { this.scene.visualEnhancements.createSparkleEffect(x, y); } seed.destroy(); } }); } // ========== AUTO-HARVESTER ========== createAutoHarvester(x, y) { if (!this.settings.buildingAnimations) return null; const harvester = { x, y, blades: [], isHarvesting: false, rotation: 0 }; // Create spinning blades for (let i = 0; i < 4; i++) { const blade = this.scene.add.graphics(); blade.lineStyle(3, 0xC0C0C0, 1); blade.lineBetween(0, 0, 15, 0); blade.setPosition(x, y); blade.setRotation((Math.PI / 2) * i); blade.setDepth(100); harvester.blades.push(blade); } this.buildings.set(`harvester_${x}_${y}`, harvester); return harvester; } animateHarvesting(harvester, cropX, cropY) { if (!harvester || harvester.isHarvesting) return; harvester.isHarvesting = true; // Spin blades for (const blade of harvester.blades) { this.scene.tweens.add({ targets: blade, rotation: blade.rotation + Math.PI * 4, duration: 1000, ease: 'Linear' }); } // Move to crop this.scene.tweens.add({ targets: harvester.blades, x: cropX, y: cropY, duration: 500, ease: 'Power2', onComplete: () => { // Harvest effect this.createHarvestEffect(cropX, cropY); // Return to base this.scene.tweens.add({ targets: harvester.blades, x: harvester.x, y: harvester.y, duration: 500, ease: 'Power2', onComplete: () => { harvester.isHarvesting = false; } }); } }); } createHarvestEffect(x, y) { // Crop particles const emitter = this.scene.add.particles(x, y, 'particle_white', { speed: { min: 30, max: 60 }, scale: { start: 0.5, end: 0 }, alpha: { start: 1, end: 0 }, lifespan: 800, quantity: 10, tint: 0xFFD700 }); this.scene.time.delayedCall(800, () => emitter.destroy()); } // ========== CONVEYOR BELT ========== createConveyorBelt(x, y, width, direction = 'right') { if (!this.settings.buildingAnimations) return null; const belt = { x, y, width, direction, items: [], speed: 50 // pixels per second }; // Create belt graphics const graphics = this.scene.add.graphics(); graphics.fillStyle(0x444444, 1); graphics.fillRect(x, y, width, 20); // Moving lines to show direction for (let i = 0; i < width; i += 20) { const line = this.scene.add.rectangle( x + i, y + 10, 10, 2, 0x888888 ); line.setDepth(99); // Animate line movement const targetX = direction === 'right' ? x + width : x; this.scene.tweens.add({ targets: line, x: targetX, duration: (width / belt.speed) * 1000, repeat: -1, ease: 'Linear' }); } belt.graphics = graphics; this.conveyorBelts.push(belt); return belt; } addItemToBelt(belt, itemSprite) { if (!belt) return; belt.items.push(itemSprite); itemSprite.setPosition(belt.x, belt.y + 10); itemSprite.setDepth(100); // Move item along belt const targetX = belt.direction === 'right' ? belt.x + belt.width : belt.x; this.scene.tweens.add({ targets: itemSprite, x: targetX, duration: (belt.width / belt.speed) * 1000, ease: 'Linear', onComplete: () => { // Remove from belt const index = belt.items.indexOf(itemSprite); if (index > -1) { belt.items.splice(index, 1); } } }); } // ========== WINDMILL ========== createWindmill(x, y) { if (!this.settings.buildingAnimations) return null; const windmill = { x, y, blades: null, powerGlow: null, isPowered: false, rotation: 0 }; // Create blades const blades = this.scene.add.graphics(); blades.lineStyle(4, 0x8B4513, 1); // Draw 4 blades for (let i = 0; i < 4; i++) { const angle = (Math.PI / 2) * i; const endX = Math.cos(angle) * 30; const endY = Math.sin(angle) * 30; blades.lineBetween(0, 0, endX, endY); } blades.setPosition(x, y); blades.setDepth(100); windmill.blades = blades; // Power glow const glow = this.scene.add.circle(x, y, 40, 0x00ffff, 0); glow.setBlendMode(Phaser.BlendModes.ADD); glow.setDepth(99); windmill.powerGlow = glow; // Rotate blades this.scene.tweens.add({ targets: blades, rotation: Math.PI * 2, duration: 3000 / this.settings.animationSpeed, repeat: -1, ease: 'Linear' }); this.windmills.push(windmill); return windmill; } setPowerState(windmill, powered) { if (!windmill) return; windmill.isPowered = powered; if (powered) { // Glow on this.scene.tweens.add({ targets: windmill.powerGlow, alpha: 0.4, duration: 500 }); // Particle trail if (this.settings.particleEffects) { const emitter = this.scene.add.particles( windmill.x, windmill.y, 'particle_white', { speed: 20, scale: { start: 0.3, end: 0 }, alpha: { start: 0.6, end: 0 }, lifespan: 1000, frequency: 200, quantity: 1, tint: 0x00ffff } ); windmill.particleEmitter = emitter; } } else { // Glow off this.scene.tweens.add({ targets: windmill.powerGlow, alpha: 0, duration: 500 }); // Stop particles if (windmill.particleEmitter) { windmill.particleEmitter.destroy(); windmill.particleEmitter = null; } } } // ========== STORAGE SILO ========== createStorageSilo(x, y, capacity = 1000) { if (!this.settings.buildingAnimations) return null; const silo = { x, y, capacity, currentAmount: 0, fillIndicator: null, fillBar: null }; // Silo structure const structure = this.scene.add.graphics(); structure.fillStyle(0x666666, 1); structure.fillRect(x - 20, y - 60, 40, 60); structure.fillCircle(x, y - 60, 20); structure.setDepth(100); silo.structure = structure; // Fill indicator (inside silo) const fillBar = this.scene.add.rectangle( x, y, 36, 0, 0xFFD700, 0.8 ); fillBar.setOrigin(0.5, 1); fillBar.setDepth(101); silo.fillBar = fillBar; // Percentage text const text = this.scene.add.text(x, y - 70, '0%', { fontSize: '12px', color: '#ffffff', fontStyle: 'bold' }); text.setOrigin(0.5); text.setDepth(102); silo.text = text; this.silos.push(silo); return silo; } updateSiloFill(silo, amount) { if (!silo) return; silo.currentAmount = Phaser.Math.Clamp(amount, 0, silo.capacity); const percentage = (silo.currentAmount / silo.capacity) * 100; const fillHeight = (percentage / 100) * 56; // Max height // Animate fill this.scene.tweens.add({ targets: silo.fillBar, height: fillHeight, duration: 500, ease: 'Power2' }); // Update text silo.text.setText(`${Math.round(percentage)}%`); } // ========== GENETICS LAB ========== createGeneticsLab(x, y) { if (!this.settings.geneticsUI) return null; const lab = { x, y, dnaHelix: null, vats: [], isActive: false }; // Lab structure const structure = this.scene.add.rectangle(x, y, 80, 60, 0x333333); structure.setStrokeStyle(2, 0x00ff00); structure.setDepth(100); lab.structure = structure; this.geneticsLab = lab; return lab; } showDNAHelixAnimation(x, y) { if (!this.settings.geneticsUI) return null; // Create DNA helix const helix = this.scene.add.container(x, y); helix.setDepth(200); // Two strands const strand1 = []; const strand2 = []; for (let i = 0; i < 20; i++) { const yPos = i * 10 - 100; const angle = (i / 20) * Math.PI * 4; const x1 = Math.cos(angle) * 15; const x2 = Math.cos(angle + Math.PI) * 15; const dot1 = this.scene.add.circle(x1, yPos, 3, 0x00ff00); const dot2 = this.scene.add.circle(x2, yPos, 3, 0x00ffff); helix.add(dot1); helix.add(dot2); strand1.push(dot1); strand2.push(dot2); // Connecting lines if (i % 3 === 0) { const line = this.scene.add.graphics(); line.lineStyle(1, 0xffffff, 0.5); line.lineBetween(x1, yPos, x2, yPos); helix.add(line); } } // Rotate helix this.scene.tweens.add({ targets: helix, rotation: Math.PI * 2, duration: 4000, repeat: -1, ease: 'Linear' }); // Pulse effect this.scene.tweens.add({ targets: helix, scale: { from: 1, to: 1.1 }, duration: 2000, yoyo: true, repeat: -1 }); this.dnaHelixAnimation = helix; return helix; } hideDNAHelixAnimation() { if (this.dnaHelixAnimation) { this.dnaHelixAnimation.destroy(); this.dnaHelixAnimation = null; } } createMutationVat(x, y) { if (!this.settings.geneticsUI) return null; const vat = { x, y, container: null, liquid: null, bubbles: null, isActive: false }; // Vat container const container = this.scene.add.graphics(); container.fillStyle(0x444444, 1); container.fillRect(x - 20, y - 40, 40, 40); container.lineStyle(2, 0x666666); container.strokeRect(x - 20, y - 40, 40, 40); container.setDepth(100); vat.container = container; // Liquid const liquid = this.scene.add.rectangle( x, y - 20, 36, 36, 0x00ff00, 0.6 ); liquid.setDepth(101); vat.liquid = liquid; this.mutationVats.push(vat); return vat; } activateMutationVat(vat) { if (!vat || vat.isActive) return; vat.isActive = true; // Bubbling effect const emitter = this.scene.add.particles( vat.x, vat.y - 40, 'particle_white', { speedY: { min: -30, max: -50 }, speedX: { min: -5, max: 5 }, scale: { start: 0.2, end: 0 }, alpha: { start: 0.8, end: 0 }, lifespan: 1000, frequency: 200, quantity: 2, tint: 0x00ff00 } ); vat.bubbles = emitter; // Lightning effect if (this.settings.particleEffects) { this.createLightningEffect(vat.x, vat.y - 60); } // Liquid glow pulse this.scene.tweens.add({ targets: vat.liquid, alpha: { from: 0.6, to: 0.9 }, duration: 800, yoyo: true, repeat: -1 }); } createLightningEffect(x, y) { const lightning = this.scene.add.graphics(); lightning.lineStyle(2, 0xffff00, 1); // Zigzag lightning let currentX = x; let currentY = y; for (let i = 0; i < 5; i++) { const nextX = currentX + (Math.random() - 0.5) * 20; const nextY = currentY + 10; lightning.lineBetween(currentX, currentY, nextX, nextY); currentX = nextX; currentY = nextY; } lightning.setDepth(200); // Flash and fade this.scene.tweens.add({ targets: lightning, alpha: 0, duration: 200, onComplete: () => lightning.destroy() }); } // ========== SETTINGS ========== saveSettings() { localStorage.setItem('novafarma_building_visuals', JSON.stringify(this.settings)); } loadSettings() { const saved = localStorage.getItem('novafarma_building_visuals'); if (saved) { this.settings = { ...this.settings, ...JSON.parse(saved) }; } } destroy() { if (this.dnaHelixAnimation) this.dnaHelixAnimation.destroy(); for (const vat of this.mutationVats) { if (vat.bubbles) vat.bubbles.destroy(); } console.log('🏭 Building Visuals System destroyed'); } }