2024-07-22 15:40:58 -05:00
|
|
|
var emitter = {};
|
|
|
|
emitter.particles = {};
|
|
|
|
emitter.life = 10;
|
|
|
|
emitter.scale = 1;
|
|
|
|
emitter.grow_for = 0;
|
|
|
|
emitter.spawn_timer = 0;
|
|
|
|
emitter.pps = 0;
|
|
|
|
emitter.color = Color.white;
|
|
|
|
|
|
|
|
emitter.draw = function()
|
|
|
|
{
|
2024-08-25 14:23:22 -05:00
|
|
|
var pars = Object.values(this.particles);
|
|
|
|
if (pars.length === 0) return;
|
2024-07-22 15:40:58 -05:00
|
|
|
render.use_shader(this.shader);
|
|
|
|
render.use_mat(this);
|
2024-08-25 14:23:22 -05:00
|
|
|
render.make_particle_ssbo(pars, this.ssbo);
|
|
|
|
render.draw(this.shape, this.ssbo, pars.length);
|
2024-07-22 15:40:58 -05:00
|
|
|
}
|
|
|
|
|
2024-08-27 20:56:45 -05:00
|
|
|
emitter.kill = function()
|
|
|
|
{
|
|
|
|
emitters.remove(this);
|
|
|
|
}
|
|
|
|
|
2024-07-22 15:40:58 -05:00
|
|
|
var std_step = function(p)
|
|
|
|
{
|
|
|
|
if (p.time < this.grow_for) {
|
|
|
|
var s = Math.lerp(0, this.scale, p.time/this.grow_for);
|
|
|
|
p.transform.scale = [s,s,s];
|
|
|
|
}
|
|
|
|
else if (p.time > (p.life - this.shrink_for)) {
|
|
|
|
var s = Math.lerp(0,this.scale,(p.life-p.time)/this.shrink_for);
|
|
|
|
p.transform.scale=[s,s,s];
|
|
|
|
} else
|
|
|
|
p.transform.scale = [this.scale,this.scale,this.scale];
|
|
|
|
}
|
|
|
|
|
|
|
|
emitter.step_hook = std_step;
|
|
|
|
|
|
|
|
emitter.spawn = function(t)
|
|
|
|
{
|
|
|
|
t ??= this.transform;
|
2024-07-23 08:40:20 -05:00
|
|
|
|
|
|
|
var par = this.dead.shift();
|
|
|
|
if (par) {
|
|
|
|
par.body.pos = t.pos;
|
|
|
|
par.transform.scale = [this.scale,this.scale,this.scale];
|
|
|
|
this.particles[par.id] = par;
|
|
|
|
par.time = 0;
|
2024-08-25 14:23:22 -05:00
|
|
|
this.spawn_hook?.(par);
|
2024-09-09 18:55:07 -05:00
|
|
|
par.life = this.life;
|
2024-07-23 08:40:20 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
par = {
|
2024-07-22 15:40:58 -05:00
|
|
|
transform: os.make_transform(),
|
|
|
|
life: this.life,
|
|
|
|
time: 0,
|
|
|
|
color: this.color
|
|
|
|
};
|
|
|
|
|
|
|
|
par.body = os.make_body(par.transform);
|
|
|
|
|
|
|
|
par.body.pos = t.pos;
|
|
|
|
par.transform.scale = [this.scale,this.scale,this.scale];
|
|
|
|
par.id = prosperon.guid();
|
|
|
|
this.particles[par.id] = par;
|
|
|
|
|
|
|
|
this.spawn_hook(par);
|
|
|
|
}
|
|
|
|
|
|
|
|
emitter.step = function(dt)
|
|
|
|
{
|
|
|
|
// update spawning particles
|
|
|
|
if (this.on && this.pps > 0) {
|
|
|
|
this.spawn_timer += dt;
|
|
|
|
var pp = 1/this.pps;
|
|
|
|
while (this.spawn_timer > pp) {
|
|
|
|
this.spawn_timer -= pp;
|
|
|
|
this.spawn();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// update all particles
|
|
|
|
for (var p of Object.values(this.particles)) {
|
|
|
|
p.time += dt;
|
2024-07-24 08:26:29 -05:00
|
|
|
this.step_hook?.(p);
|
2024-09-09 18:55:07 -05:00
|
|
|
|
|
|
|
if (this.kill_hook?.(p) || p.time >= p.life) {
|
2024-08-25 14:23:22 -05:00
|
|
|
this.die_hook?.(p);
|
2024-07-23 08:40:20 -05:00
|
|
|
this.dead.push(this.particles[p.id]);
|
2024-07-22 15:40:58 -05:00
|
|
|
delete this.particles[p.id];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
emitter.burst = function(count, t) {
|
|
|
|
for (var i = 0; i < count; i++) this.spawn(t);
|
|
|
|
}
|
|
|
|
|
2024-08-25 14:23:22 -05:00
|
|
|
var emitters = [];
|
|
|
|
|
2024-07-22 15:40:58 -05:00
|
|
|
var make_emitter = function()
|
|
|
|
{
|
|
|
|
var e = Object.create(emitter);
|
|
|
|
e.ssbo = render.make_textssbo();
|
2024-07-23 17:21:27 -05:00
|
|
|
e.shape = shape.centered_quad;
|
2024-08-02 20:52:50 -05:00
|
|
|
e.shader = "shaders/baseparticle.cg";
|
2024-07-23 08:40:20 -05:00
|
|
|
e.dead = [];
|
2024-08-25 14:23:22 -05:00
|
|
|
emitters.push(e);
|
2024-07-22 15:40:58 -05:00
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2024-08-25 14:23:22 -05:00
|
|
|
function update_emitters(dt)
|
|
|
|
{
|
|
|
|
for (var e of emitters)
|
|
|
|
e.step(dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
function draw_emitters()
|
|
|
|
{
|
|
|
|
for (var e of emitters) e.draw();
|
|
|
|
}
|
|
|
|
|
|
|
|
return {make_emitter, update_emitters, draw_emitters};
|