game.system.Particle = () => { "use strict"; const particleSpawners = {}; const particleSpawner = ({colors, maxAmount, minAmount, minLife, maxLife, minRadius, maxRadius, maxSpeed, spawnFunction}) => { return Array(randomInRange(minAmount, maxAmount)).fill(0).map(() => { let particleSpec = { x: Math.random(), y: Math.random(), dx: Math.random() * maxSpeed - maxSpeed / 2, dy: Math.random() * maxSpeed - maxSpeed / 2, radius: randomInRange(minRadius, maxRadius), color: colors[randomInRange(0, colors.length-1)], lifetime: randomInRange(minLife, maxLife), elapsed: 0, }; if (spawnFunction) { particleSpec = {...particleSpec, ...spawnFunction(particleSpec)}; } return particleSpec; }); }; const update = (elapsedTime, entities, _changedIds) => { for (let id in entities) { const entity = entities[id]; if (entity.hasComponent("particles")) { if (!particleSpawners[entity.id]) { particleSpawners[entity.id] = particleSpawner(entity.components.particles.spec.spec); entities[id].particleSprite = game.graphics.Sprite({ drawFunction: (elapsedTime, {x, y, width, height}, context) => { let particleSpawner = particleSpawners[entity.id]; particleSpawner.map((particleSpec) => particleSpec.elapsed += elapsedTime); particleSpawners[id] = particleSpawner.filter((particleSpec) => particleSpec.lifetime > particleSpec.elapsed); particleSpawner = particleSpawners[id]; if (particleSpawner.length === 0) { entities[id].removeComponent("alive"); } particleSpawner.map((particleSpec) => { const position = {x: (particleSpec.x * width) + x + particleSpec.dx * particleSpec.elapsed, y: (particleSpec.y * height) + y + particleSpec.dy * particleSpec.elapsed}; const fill = context.fillStyle; context.fillStyle = particleSpec.color; context.beginPath(); context.arc(position.x, position.y, particleSpec.radius, 0, 2 * Math.PI); context.fill(); context.fillStyle = fill; }); } }); } } } return new Set(); }; return { update }; };