caro5 / client /src /game /effects /ParticleSystem.ts
Pedro de Carvalho
Add game effect
dbb749a
Raw
History Blame Contribute Delete
2.01 kB
import { Container, Graphics } from 'pixi.js'
interface Particle {
x: number
y: number
vx: number
vy: number
life: number
maxLife: number
color: number
size: number
alpha: number
}
export interface EmitConfig {
count: number
x: number
y: number
color: number
spread: number // velocity spread px/s
speed: number // base speed px/s
size: number
life: number // seconds
gravity?: number
}
export class ParticleSystem {
container: Container
private particles: Particle[] = []
private g: Graphics
private _running = false
constructor(parent: Container) {
this.container = new Container()
parent.addChild(this.container)
this.g = new Graphics()
this.container.addChild(this.g)
}
emit(cfg: EmitConfig): void {
for (let i = 0; i < cfg.count; i++) {
const angle = Math.random() * Math.PI * 2
const speed = cfg.speed * (0.5 + Math.random() * 0.5)
this.particles.push({
x: cfg.x,
y: cfg.y,
vx: Math.cos(angle) * speed + (Math.random() - 0.5) * cfg.spread,
vy: Math.sin(angle) * speed + (Math.random() - 0.5) * cfg.spread,
life: cfg.life,
maxLife: cfg.life,
color: cfg.color,
size: cfg.size * (0.5 + Math.random() * 0.5),
alpha: 1,
})
}
this._running = true
}
update(dt: number): void {
if (!this._running) return
const gravity = 200
let alive = false
this.g.clear()
for (const p of this.particles) {
p.life -= dt
if (p.life <= 0) continue
p.x += p.vx * dt
p.y += p.vy * dt
p.vy += gravity * dt
p.alpha = Math.max(0, p.life / p.maxLife)
this.g.circle(p.x, p.y, p.size * p.alpha)
this.g.fill({ color: p.color, alpha: p.alpha })
alive = true
}
this.particles = this.particles.filter((p) => p.life > 0)
this._running = alive
}
clear(): void {
this.particles.length = 0
this.g.clear()
this._running = false
}
}