initial commit
This commit is contained in:
commit
e8c3f9862a
193 files changed
+29795
No files matched your search
@@ -0,0 +1,109 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user