diff --git a/2048.css b/2048.css index aeefef8..c3d840c 100644 --- a/2048.css +++ b/2048.css @@ -1200,6 +1200,70 @@ h1 { 100% { transform: translateY(-45px) translateX(-18px); } } +/* Floating Particles from Bottom */ +.floating-particles { + position: fixed; + inset: 0; + overflow: hidden; + pointer-events: none; + z-index: 0; /* Di bawah semua elemen game */ +} + +.floating-particle { + position: absolute; + bottom: -20px; + width: 8px; + height: 8px; + background: rgba(0, 234, 255, 0.6); + border-radius: 50%; + filter: blur(1px); + box-shadow: 0 0 15px currentColor; + animation: floatUp linear infinite; +} + +@keyframes floatUp { + 0% { + transform: translateY(0) translateX(0) scale(0.5); + opacity: 0; + } + 10% { + opacity: 1; + } + 90% { + opacity: 0.6; + } + 100% { + transform: translateY(-100vh) translateX(var(--drift, 0)) scale(1.2); + opacity: 0; + } +} + +/* Different particle colors */ +.floating-particle.cyan { + background: rgba(0, 234, 255, 0.7); + box-shadow: 0 0 20px rgba(0, 234, 255, 0.8); +} + +.floating-particle.pink { + background: rgba(255, 0, 255, 0.6); + box-shadow: 0 0 20px rgba(255, 0, 255, 0.7); +} + +.floating-particle.purple { + background: rgba(200, 100, 255, 0.6); + box-shadow: 0 0 20px rgba(200, 100, 255, 0.7); +} + +.floating-particle.green { + background: rgba(0, 255, 200, 0.6); + box-shadow: 0 0 20px rgba(0, 255, 200, 0.7); +} + +.floating-particle.orange { + background: rgba(255, 170, 0, 0.6); + box-shadow: 0 0 20px rgba(255, 170, 0, 0.7); +} + .starfield { position: fixed; inset: 0; diff --git a/2048.html b/2048.html index ebecb5f..127733d 100644 --- a/2048.html +++ b/2048.html @@ -15,6 +15,7 @@ + @@ -381,9 +382,10 @@ + - + \ No newline at end of file diff --git a/Floating_Particles_2048.js b/Floating_Particles_2048.js new file mode 100644 index 0000000..c08ce20 --- /dev/null +++ b/Floating_Particles_2048.js @@ -0,0 +1,48 @@ +// Floating Particles System - Particles rising from bottom +(function() { + const container = document.getElementById('floating-particles'); + if (!container) return; + + const particleColors = ['cyan', 'pink', 'purple', 'green', 'orange']; + const particleCount = 25; // Number of particles + + function createParticle() { + const particle = document.createElement('div'); + particle.className = `floating-particle ${particleColors[Math.floor(Math.random() * particleColors.length)]}`; + + // Random horizontal position + const leftPos = Math.random() * 100; + particle.style.left = leftPos + '%'; + + // Random drift amount (horizontal movement during float) + const drift = (Math.random() - 0.5) * 150; // -75px to +75px + particle.style.setProperty('--drift', drift + 'px'); + + // Random animation duration (slower = more dramatic) + const duration = 8 + Math.random() * 10; // 8-18 seconds + particle.style.animationDuration = duration + 's'; + + // Random delay for staggered effect + const delay = Math.random() * 5; + particle.style.animationDelay = delay + 's'; + + // Random size variation + const size = 6 + Math.random() * 8; // 6-14px + particle.style.width = size + 'px'; + particle.style.height = size + 'px'; + + container.appendChild(particle); + + // Remove and recreate after animation completes + setTimeout(() => { + particle.remove(); + createParticle(); + }, (duration + delay) * 1000); + } + + // Initialize particles + for (let i = 0; i < particleCount; i++) { + // Stagger initial creation + setTimeout(() => createParticle(), i * 200); + } +})(); \ No newline at end of file