import { System } from '../core/System.js'; import { Palette } from '../core/Palette.js'; import { SystemName, ComponentType, VFXType } from '../core/Constants.js'; export class VFXSystem extends System { constructor() { super(SystemName.VFX); this.requiredComponents = []; this.priority = 40; this.particles = []; } process(deltaTime, _entities) { const playerController = this.engine.systems.find(s => s.name === SystemName.PLAYER_CONTROLLER); const player = playerController ? playerController.getPlayerEntity() : null; const playerPos = player ? player.getComponent(ComponentType.POSITION) : null; for (let i = this.particles.length - 1; i >= 0; i--) { const p = this.particles[i]; // Update lifetime p.lifetime -= deltaTime; if (p.lifetime <= 0) { this.particles.splice(i, 1); continue; } // Behavior logic if (p.type === VFXType.ABSORPTION && playerPos) { // Attract to player const dx = playerPos.x - p.x; const dy = playerPos.y - p.y; const dist = Math.sqrt(dx * dx + dy * dy); if (dist > 5) { p.vx += (dx / dist) * 800 * deltaTime; p.vy += (dy / dist) * 800 * deltaTime; // Add some drag to make it smooth p.vx *= 0.95; p.vy *= 0.95; } else { // Arrived this.particles.splice(i, 1); continue; } } else { // Basic drag for impact particles p.vx *= 0.9; p.vy *= 0.9; } // Update position p.x += p.vx * deltaTime; p.y += p.vy * deltaTime; } } createImpact(x, y, color = Palette.WHITE, angle = null) { const count = 8; for (let i = 0; i < count; i++) { let vx, vy; if (angle !== null) { // Splash in the direction of hit + some spread const spread = (Math.random() - 0.5) * 2; const speed = 50 + Math.random() * 150; vx = Math.cos(angle + spread) * speed; vy = Math.sin(angle + spread) * speed; } else { vx = (Math.random() - 0.5) * 150; vy = (Math.random() - 0.5) * 150; } this.particles.push({ x, y, vx, vy, lifetime: 0.2 + Math.random() * 0.3, size: 1 + Math.random() * 2, color: color, type: VFXType.IMPACT }); } } createAbsorption(x, y, color = Palette.CYAN) { for (let i = 0; i < 12; i++) { // Start with a small explosion then attract this.particles.push({ x, y, vx: (Math.random() - 0.5) * 100, vy: (Math.random() - 0.5) * 100, lifetime: 1.5, size: 2, color: color, type: VFXType.ABSORPTION }); } } getParticles() { return this.particles; } }