import { Vector2D } from './Vector2D.js'; const MAX_PARTICLES = 450; export class ParticleSystem { constructor() { this.particles = []; } burst( x, y, { count = 12, speed = 150, direction = 0, spread = Math.PI * 2, life = 0.4, size = 4, color = [1, 1, 1, 1], gravity = 0, drag = 0, shape = 'square', additive = false, endSize = null, spin = 0, } = {}, ) { for (let i = 0; i < count; i++) { if (this.particles.length >= MAX_PARTICLES) return; const angle = direction + (Math.random() - 0.5) * spread; const magnitude = speed * (0.4 + Math.random() * 0.8); const velocity = new Vector2D(Math.cos(angle), Math.sin(angle)).mulS(magnitude); const lifetime = life * (0.6 + Math.random() * 0.6); const startSize = size * (0.6 + Math.random() * 0.8); this.particles.push({ pos: new Vector2D(x, y), velocity, gravity, drag, life: lifetime, maxLife: lifetime, size: startSize, endSize: endSize === null ? startSize * 0.15 : endSize * (0.6 + Math.random() * 0.8), color: [...color], shape, additive, angle: Math.random() * Math.PI * 2, spin: (Math.random() - 0.5) * (spin * 2), }); } } update(dt) { const { particles } = this; for (let i = particles.length - 1; i >= 0; i--) { const particle = particles[i]; particle.pos = particle.velocity.mulS(dt).addV(particle.pos); particle.velocity.y += particle.gravity * dt; if (particle.drag > 0) { particle.velocity = particle.velocity.mulS(Math.max(0, 1 - particle.drag * dt)); } particle.angle += particle.spin * dt; particle.life -= dt; if (particle.life <= 0) { particles.splice(i, 1); } } } draw(renderer) { const additive = this.particles.filter((particle) => particle.additive); const normal = this.particles.filter((particle) => !particle.additive); if (additive.length > 0) renderer.setBlendMode('additive'); for (const particle of additive) this._drawParticle(renderer, particle); if (additive.length > 0) renderer.setBlendMode('normal'); for (const particle of normal) this._drawParticle(renderer, particle); } _drawParticle(renderer, particle) { const alpha = Math.max(0, particle.life / particle.maxLife); const progress = 1 - alpha; const size = particle.size + (particle.endSize - particle.size) * progress; const color = [ particle.color[0], particle.color[1], particle.color[2], particle.color[3] * alpha, ]; const texture = particle.shape === 'glow' ? renderer.glowTexture : renderer.whiteTexture; renderer.drawTexture( texture, particle.pos.x - size / 2, particle.pos.y - size / 2, size, size, color, particle.angle, ); } clear() { this.particles.length = 0; } }