/* ------------------------ 3. VISUAL EFFECTS ------------------------ */ function triggerComboEffect(mergedCells, comboCount) { if (mergedCells.length === 0) return; mergedCells.forEach(cell => { const tile = document.getElementById(`${cell.r}-${cell.c}`); if (!tile) return; tile.classList.add('merge'); setTimeout(() => tile.classList.remove('merge'), 300); createParticleBurst(tile); tile.style.boxShadow = '0 0 40px currentColor'; setTimeout(() => { tile.style.boxShadow = ''; }, 300); const rect = tile.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const tileValue = parseInt(tile.textContent); createScorePopup(centerX, centerY, tileValue); }); if (comboCount >= 2) { showComboPopup(comboCount); } } function showComboPopup(comboCount) { const board = document.getElementById('board'); if (!board) return; const rect = board.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const popup = document.createElement('div'); popup.className = 'combo-popup'; popup.style.left = centerX + 'px'; popup.style.top = centerY + 'px'; popup.style.position = 'fixed'; popup.style.fontWeight = '900'; popup.style.pointerEvents = 'none'; popup.style.zIndex = '9999'; popup.style.transform = 'translate(-50%, -50%)'; popup.style.textTransform = 'uppercase'; popup.style.letterSpacing = '3px'; if (comboCount === 2) { popup.textContent = 'COMBO x2!'; popup.style.fontSize = '36px'; popup.style.color = '#00ff99'; popup.style.textShadow = '0 0 30px rgba(0, 255, 153, 1), 0 0 50px rgba(0, 255, 153, 0.5)'; } else if (comboCount === 3) { popup.textContent = 'AMAZING x3!'; popup.style.fontSize = '42px'; popup.style.color = '#ff00ff'; popup.style.textShadow = '0 0 35px rgba(255, 0, 255, 1), 0 0 60px rgba(255, 0, 255, 0.6)'; } else if (comboCount >= 4) { popup.textContent = 'PERFECT x' + comboCount + '!'; popup.style.fontSize = '48px'; popup.style.color = '#ffd700'; popup.style.textShadow = '0 0 40px rgba(255, 215, 0, 1), 0 0 70px rgba(255, 215, 0, 0.7)'; } document.body.appendChild(popup); popup.animate([ { transform: 'translate(-50%, -50%) scale(0.3) rotate(-10deg)', opacity: 0 }, { transform: 'translate(-50%, -50%) scale(1.3) rotate(5deg)', opacity: 1, offset: 0.3 }, { transform: 'translate(-50%, -50%) scale(1.1) rotate(-2deg)', opacity: 1, offset: 0.6 }, { transform: 'translate(-50%, -50%) scale(0.8) rotate(0deg)', opacity: 0 } ], { duration: 1200, easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)' }).onfinish = () => popup.remove(); } function createParticleBurst(tileElement) { const rect = tileElement.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const tileValue = parseInt(tileElement.textContent); const tileColor = getTileColor(tileValue); const particleCount = 8 + Math.floor(Math.random() * 5); for (let i = 0; i < particleCount; i++) { const particle = document.createElement('div'); particle.className = 'merge-particle'; particle.style.left = centerX + 'px'; particle.style.top = centerY + 'px'; particle.style.background = tileColor; document.body.appendChild(particle); const angle = (Math.PI * 2 * i) / particleCount + (Math.random() - 0.5) * 0.5; const velocity = 60 + Math.random() * 40; const tx = Math.cos(angle) * velocity; const ty = Math.sin(angle) * velocity; particle.animate([ { transform: 'translate(0, 0) scale(1)', opacity: 1 }, { transform: `translate(${tx}px, ${ty}px) scale(0)`, opacity: 0 } ], { duration: 500 + Math.random() * 200, easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)' }).onfinish = () => particle.remove(); } } function createScorePopup(x, y, score) { const popup = document.createElement('div'); popup.className = 'score-popup'; popup.textContent = '+' + score; popup.style.left = x + 'px'; popup.style.top = y + 'px'; popup.style.position = 'fixed'; popup.style.fontSize = '24px'; popup.style.fontWeight = '900'; popup.style.color = '#ffd700'; popup.style.textShadow = '0 0 20px rgba(255, 215, 0, 0.8)'; popup.style.pointerEvents = 'none'; popup.style.zIndex = '9999'; popup.style.transform = 'translate(-50%, -50%)'; document.body.appendChild(popup); popup.animate([ { transform: 'translate(-50%, -50%) scale(0.5)', opacity: 0 }, { transform: 'translate(-50%, -70px) scale(1.2)', opacity: 1, offset: 0.3 }, { transform: 'translate(-50%, -120px) scale(1)', opacity: 0 } ], { duration: 1000, easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)' }).onfinish = () => popup.remove(); } function getTileColor(value) { const colors = { 2: '#00eaff', 4: '#00ff99', 8: '#ff00ff', 16: '#ff0066', 32: '#ffaa00', 64: '#ff0000', 128: '#5f00ff', 256: '#00ffea', 512: '#ff00aa', 1024: '#00ffaa', 2048: '#ffd700' }; return colors[value] || '#00eaff'; }