Spaces:
Runtime error
Runtime error
File size: 2,008 Bytes
dbb749a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | 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
}
}
|