/** * Cosmic Garden - Particle System * Creates visual particle effects for clicks and achievements */ const Particles = { /** * Create sparkle particles on click */ createClickParticles(x, y, count = 8) { const colors = ['#ffd700', '#9b59b6', '#3498db', '#2ecc71', '#ffffff']; for (let i = 0; i < count; i++) { const particle = document.createElement('div'); particle.className = 'particle'; // Random properties const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5); const velocity = 50 + Math.random() * 50; const size = 6 + Math.random() * 8; const color = colors[Math.floor(Math.random() * colors.length)]; particle.style.cssText = ` left: ${x}px; top: ${y}px; width: ${size}px; height: ${size}px; background: ${color}; border-radius: 50%; pointer-events: none; position: fixed; z-index: 998; `; document.body.appendChild(particle); // Animate const animation = particle.animate([ { transform: 'translate(-50%, -50%) scale(1)', opacity: 1 }, { transform: `translate(calc(-50% + ${Math.cos(angle) * velocity}px), calc(-50% + ${Math.sin(angle) * velocity}px)) scale(0)`, opacity: 0 } ], { duration: 600 + Math.random() * 200, easing: 'cubic-bezier(0, 0.9, 0.57, 1)' }); animation.onfinish = () => particle.remove(); } }, /** * Create achievement unlock effect */ createAchievementEffect(x, y) { const colors = ['#ffd700', '#ff6b6b', '#4ecdc4', '#45b7d1', '#96ceb4']; // Burst of particles for (let i = 0; i < 20; i++) { const particle = document.createElement('div'); particle.className = 'particle achievement-particle'; const angle = (Math.PI * 2 * i) / 20; const velocity = 80 + Math.random() * 60; const size = 8 + Math.random() * 12; const color = colors[Math.floor(Math.random() * colors.length)]; particle.style.cssText = ` left: ${x}px; top: ${y}px; width: ${size}px; height: ${size}px; background: ${color}; border-radius: 50%; pointer-events: none; position: fixed; z-index: 998; box-shadow: 0 0 10px ${color}; `; document.body.appendChild(particle); const animation = particle.animate([ { transform: 'translate(-50%, -50%) scale(1)', opacity: 1 }, { transform: `translate(calc(-50% + ${Math.cos(angle) * velocity}px), calc(-50% + ${Math.sin(angle) * velocity}px)) scale(0.5)`, opacity: 0.8 }, { transform: `translate(calc(-50% + ${Math.cos(angle) * velocity * 1.5}px), calc(-50% + ${Math.sin(angle) * velocity * 1.5}px)) scale(0)`, opacity: 0 } ], { duration: 1000, easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)' }); animation.onfinish = () => particle.remove(); } }, /** * Create building purchase effect */ createBuildingEffect(x, y) { const colors = ['#2ecc71', '#27ae60', '#1abc9c']; for (let i = 0; i < 12; i++) { const particle = document.createElement('div'); particle.className = 'particle building-particle'; const angle = (Math.PI * 2 * i) / 12; const velocity = 60 + Math.random() * 40; const size = 5 + Math.random() * 6; const color = colors[Math.floor(Math.random() * colors.length)]; particle.style.cssText = ` left: ${x}px; top: ${y}px; width: ${size}px; height: ${size}px; background: ${color}; border-radius: 2px; pointer-events: none; position: fixed; z-index: 998; `; document.body.appendChild(particle); const animation = particle.animate([ { transform: 'translate(-50%, -50%) rotate(0deg) scale(1)', opacity: 1 }, { transform: `translate(calc(-50% + ${Math.cos(angle) * velocity}px), calc(-50% + ${Math.sin(angle) * velocity}px)) rotate(${360 + Math.random() * 180}deg) scale(0)`, opacity: 0 } ], { duration: 700, easing: 'ease-out' }); animation.onfinish = () => particle.remove(); } }, /** * Create ambient floating stars in the background */ createAmbientStars(count = 15) { for (let i = 0; i < count; i++) { const star = document.createElement('div'); star.className = 'ambient-star'; const size = 2 + Math.random() * 3; const left = Math.random() * 100; const delay = Math.random() * 5; const duration = 3 + Math.random() * 2; star.style.cssText = ` width: ${size}px; height: ${size}px; left: ${left}%; top: ${Math.random() * 100}%; animation-delay: ${delay}s; animation-duration: ${duration}s; `; document.getElementById('game-container').appendChild(star); } }, /** * Create prestige reset effect - cosmic explosion */ createPrestigeEffect(x, y) { const colors = ['#ffd700', '#9b59b6', '#3498db', '#ffffff', '#e74c3c']; // Outer ring burst for (let i = 0; i < 30; i++) { const particle = document.createElement('div'); particle.className = 'particle prestige-particle'; const angle = (Math.PI * 2 * i) / 30; const velocity = 100 + Math.random() * 80; const size = 10 + Math.random() * 15; const color = colors[Math.floor(Math.random() * colors.length)]; particle.style.cssText = ` left: ${x}px; top: ${y}px; width: ${size}px; height: ${size}px; background: ${color}; border-radius: 50%; pointer-events: none; position: fixed; z-index: 998; box-shadow: 0 0 15px ${color}, 0 0 30px ${color}; `; document.body.appendChild(particle); const animation = particle.animate([ { transform: 'translate(-50%, -50%) scale(1)', opacity: 1 }, { transform: `translate(calc(-50% + ${Math.cos(angle) * velocity}px), calc(-50% + ${Math.sin(angle) * velocity}px)) scale(1.5)`, opacity: 0.8 }, { transform: `translate(calc(-50% + ${Math.cos(angle) * velocity * 2}px), calc(-50% + ${Math.sin(angle) * velocity * 2}px)) scale(0)`, opacity: 0 } ], { duration: 1500, easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)' }); animation.onfinish = () => particle.remove(); } // Inner sparkle burst for (let i = 0; i < 15; i++) { const sparkle = document.createElement('div'); sparkle.className = 'particle'; const angle = Math.random() * Math.PI * 2; const velocity = 50 + Math.random() * 50; const size = 4 + Math.random() * 6; sparkle.style.cssText = ` left: ${x}px; top: ${y}px; width: ${size}px; height: ${size}px; background: #ffd700; border-radius: 50%; pointer-events: none; position: fixed; z-index: 998; box-shadow: 0 0 10px #ffd700; `; document.body.appendChild(sparkle); const animation = sparkle.animate([ { transform: 'translate(-50%, -50%) scale(1)', opacity: 1 }, { transform: `translate(calc(-50% + ${Math.cos(angle) * velocity}px), calc(-50% + ${Math.sin(angle) * velocity}px)) scale(0)`, opacity: 0 } ], { duration: 800, easing: 'ease-out' }); animation.onfinish = () => sparkle.remove(); } }, /** * Create a Golden Starbloom burst - a shimmering golden explosion. */ createGoldenEffect(x, y) { const colors = ['#ffd700', '#ffe469', '#fff2a8', '#ffcf3f', '#ffffff']; // Outer ring of glowing golden particles for (let i = 0; i < 24; i++) { const particle = document.createElement('div'); particle.className = 'particle golden-bloom-particle'; const angle = (Math.PI * 2 * i) / 24; const velocity = 90 + Math.random() * 70; const size = 8 + Math.random() * 10; const color = colors[Math.floor(Math.random() * colors.length)]; particle.style.cssText = ` left: ${x}px; top: ${y}px; width: ${size}px; height: ${size}px; background: ${color}; border-radius: 50%; pointer-events: none; position: fixed; z-index: 998; box-shadow: 0 0 12px ${color}, 0 0 24px #ffd700; `; document.body.appendChild(particle); const animation = particle.animate([ { transform: 'translate(-50%, -50%) scale(1)', opacity: 1 }, { transform: `translate(calc(-50% + ${Math.cos(angle) * velocity}px), calc(-50% + ${Math.sin(angle) * velocity}px)) scale(1.3)`, opacity: 0.85 }, { transform: `translate(calc(-50% + ${Math.cos(angle) * velocity * 2}px), calc(-50% + ${Math.sin(angle) * velocity * 2}px)) scale(0)`, opacity: 0 } ], { duration: 1200, easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)' }); animation.onfinish = () => particle.remove(); } // Golden sparkle burst for (let i = 0; i < 12; i++) { const sparkle = document.createElement('div'); sparkle.className = 'particle golden-sparkle'; const angle = Math.random() * Math.PI * 2; const velocity = 40 + Math.random() * 50; const size = 3 + Math.random() * 4; sparkle.style.cssText = ` left: ${x}px; top: ${y}px; width: ${size}px; height: ${size}px; background: #fff2a8; border-radius: 50%; pointer-events: none; position: fixed; z-index: 999; box-shadow: 0 0 10px #ffd700; `; document.body.appendChild(sparkle); const animation = sparkle.animate([ { transform: 'translate(-50%, -50%) scale(1)', opacity: 1 }, { transform: `translate(calc(-50% + ${Math.cos(angle) * velocity}px), calc(-50% + ${Math.sin(angle) * velocity}px)) scale(0)`, opacity: 0 } ], { duration: 700, easing: 'ease-out' }); animation.onfinish = () => sparkle.remove(); } }, }; // Make globally accessible window.Particles = Particles;