diff --git a/index.html b/index.html index ea3b80a..f7d9cdb 100644 --- a/index.html +++ b/index.html @@ -96,6 +96,8 @@ body{background:var(--bg);color:var(--text);font-family:'SF Mono','Cascadia Code @keyframes toast-in{from{transform:translateX(40px);opacity:0}to{transform:translateX(0);opacity:0.95}} @keyframes toast-out{from{opacity:0.95;transform:translateX(0)}to{opacity:0;transform:translateX(40px)}} @keyframes res-pulse{0%{transform:scale(1)}50%{transform:scale(1.18);color:#80d0ff}100%{transform:scale(1)}} +.particle{position:fixed;pointer-events:none;z-index:150;border-radius:50%;animation:particle-fly 0.6s ease-out forwards} +@keyframes particle-fly{0%{opacity:1;transform:translate(0,0) scale(1)}100%{opacity:0;transform:translate(var(--px),var(--py)) scale(0.2)}} @keyframes res-shake{0%,100%{transform:translateX(0)}20%{transform:translateX(-3px)}40%{transform:translateX(3px)}60%{transform:translateX(-2px)}80%{transform:translateX(2px)}} .r-val.pulse{animation:res-pulse 0.35s ease-out} .r-val.shake{animation:res-shake 0.3s ease-out;color:var(--red)!important} diff --git a/js/engine.js b/js/engine.js index 361f1aa..a0e6048 100644 --- a/js/engine.js +++ b/js/engine.js @@ -303,6 +303,12 @@ function buyBuilding(id) { updateRates(); const label = qty > 1 ? `x${qty}` : ''; log(`Built ${def.name} ${label} (total: ${G.buildings[id]})`); + // Particle burst on purchase + const btn = document.querySelector('[onclick="buyBuilding(\'' + id + '\')"]'); + if (btn) { + const rect = btn.getBoundingClientRect(); + spawnParticles(rect.left + rect.width / 2, rect.top + rect.height / 2, '#4a9eff', 10); + } render(); } @@ -329,6 +335,12 @@ function buyProject(id) { } updateRates(); + // Gold particle burst on project completion + const pBtn = document.querySelector('[onclick="buyProject(\'' + id + '\')"]'); + if (pBtn) { + const rect = pBtn.getBoundingClientRect(); + spawnParticles(rect.left + rect.width / 2, rect.top + rect.height / 2, '#ffd700', 16); + } render(); } diff --git a/js/utils.js b/js/utils.js index d8828d2..f973830 100644 --- a/js/utils.js +++ b/js/utils.js @@ -285,6 +285,31 @@ function getClickPower() { return (1 + Math.floor(G.buildings.autocoder * 0.5) + Math.max(0, (G.phase - 1)) * 2) * G.codeBoost; } +/** + * Spawns a burst of particles at (x, y) for visual feedback. + * @param {number} x - Center X in viewport pixels. + * @param {number} y - Center Y in viewport pixels. + * @param {string} color - Particle color (CSS value). + * @param {number} [count=12] - Number of particles. + */ +function spawnParticles(x, y, color, count) { + count = count || 12; + for (let i = 0; i < count; i++) { + const el = document.createElement('div'); + el.className = 'particle'; + const size = 3 + Math.random() * 4; + const angle = (Math.PI * 2 * i / count) + (Math.random() - 0.5) * 0.5; + const dist = 30 + Math.random() * 40; + const px = Math.cos(angle) * dist; + const py = Math.sin(angle) * dist; + el.style.cssText = + 'left:' + x + 'px;top:' + y + 'px;width:' + size + 'px;height:' + size + + 'px;background:' + color + ';--px:' + px + 'px;--py:' + py + 'px'; + document.body.appendChild(el); + setTimeout(function() { el.remove(); }, 650); + } +} + /** * Calculates production rates for all resources based on buildings and boosts. */ \ No newline at end of file