622a9fd170
Inverted tower-defense browser game — deploy enemies yourself, tower auto-kills them, pocket credits, upgrade weapons. HTML + Canvas + vanilla JS, no build step. Co-Authored-By: claude-flow <ruv@ruv.net>
60 lines
1.5 KiB
JavaScript
60 lines
1.5 KiB
JavaScript
// ═══ particles.js ═══
|
|
// ============================================================
|
|
// PARTICLES.JS — Particles, floaters, damage numbers
|
|
// ============================================================
|
|
|
|
const MAX_PARTICLES = 400;
|
|
const MAX_FLOATERS = 40;
|
|
|
|
function spawnParticle(x, y, color, vx, vy, life, radius, decay) {
|
|
if (G.particles.length >= MAX_PARTICLES) return;
|
|
G.particles.push({ x, y, color, vx, vy, life, radius, decay });
|
|
}
|
|
|
|
function spawnParticleBurst(x, y, color, count) {
|
|
const free = MAX_PARTICLES - G.particles.length;
|
|
const actual = Math.min(count, free);
|
|
for (let i = 0; i < actual; i++) {
|
|
const angle = Math.random() * Math.PI * 2;
|
|
const speed = 1 + Math.random() * 3.5;
|
|
spawnParticle(
|
|
x, y, color,
|
|
Math.cos(angle) * speed,
|
|
Math.sin(angle) * speed,
|
|
0.9 + Math.random() * 0.1,
|
|
2 + Math.random() * 4,
|
|
0.03 + Math.random() * 0.04
|
|
);
|
|
}
|
|
}
|
|
|
|
function spawnFloater(x, y, text, color, scale = 1.0) {
|
|
if (G.floaters.length >= MAX_FLOATERS) return;
|
|
G.floaters.push({
|
|
x, y, text, color, scale,
|
|
life: 1,
|
|
vy: -1.0 - Math.random() * 0.5,
|
|
vx: (Math.random() - 0.5) * 0.8,
|
|
});
|
|
}
|
|
|
|
function updateParticles() {
|
|
compactLiveArray(G.particles, p => {
|
|
p.x += p.vx;
|
|
p.y += p.vy;
|
|
p.vx *= 0.91;
|
|
p.vy *= 0.91;
|
|
p.life -= p.decay;
|
|
return p.life > 0;
|
|
});
|
|
}
|
|
|
|
function updateFloaters() {
|
|
compactLiveArray(G.floaters, f => {
|
|
f.x += f.vx;
|
|
f.y += f.vy;
|
|
f.life -= 0.018;
|
|
return f.life > 0;
|
|
});
|
|
}
|