prosperon/scripts/particle.js

142 lines
3 KiB
JavaScript
Raw Normal View History

2024-07-22 15:40:58 -05:00
var emitter = {};
emitter.life = 10;
emitter.scale = 1;
emitter.grow_for = 0;
emitter.spawn_timer = 0;
emitter.pps = 0;
emitter.color = Color.white;
2024-09-30 11:26:56 -05:00
var ssbo;
2024-09-26 11:36:09 -05:00
emitter.kill = function () {
2024-08-27 20:56:45 -05:00
emitters.remove(this);
2024-09-26 11:36:09 -05:00
};
2024-08-27 20:56:45 -05:00
2024-09-26 11:36:09 -05:00
var std_step = function (p) {
2024-07-22 15:40:58 -05:00
if (p.time < this.grow_for) {
2024-09-26 11:36:09 -05:00
var s = Math.lerp(0, this.scale, p.time / this.grow_for);
2024-09-30 13:06:31 -05:00
p.transform.scale = s;
2024-09-26 11:36:09 -05:00
} else if (p.time > p.life - this.shrink_for) {
var s = Math.lerp(0, this.scale, (p.life - p.time) / this.shrink_for);
2024-09-30 13:06:31 -05:00
p.transform.scale = s;
2024-09-26 11:36:09 -05:00
} else p.transform.scale = [this.scale, this.scale, this.scale];
};
2024-07-22 15:40:58 -05:00
emitter.step_hook = std_step;
2024-09-26 11:36:09 -05:00
emitter.spawn = function (t) {
2024-07-22 15:40:58 -05:00
t ??= this.transform;
2024-09-26 11:36:09 -05:00
var par = this.dead.shift();
if (par) {
par.body.pos = t.pos;
2024-09-30 13:06:31 -05:00
par.transform.scale = this.scale;
this.particles.push(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;
return;
}
par = {
2024-07-22 15:40:58 -05:00
transform: os.make_transform(),
life: this.life,
time: 0,
2024-09-26 11:36:09 -05:00
color: this.color,
2024-07-22 15:40:58 -05:00
};
par.body = os.make_body(par.transform);
par.body.pos = t.pos;
2024-09-30 13:06:31 -05:00
par.transform.scale = this.scale;
this.particles.push(par);
2024-07-22 15:40:58 -05:00
this.spawn_hook(par);
2024-09-26 11:36:09 -05:00
};
2024-07-22 15:40:58 -05:00
2024-09-26 11:36:09 -05:00
emitter.step = function (dt) {
2024-07-22 15:40:58 -05:00
// update spawning particles
if (this.on && this.pps > 0) {
this.spawn_timer += dt;
2024-09-26 11:36:09 -05:00
var pp = 1 / this.pps;
2024-07-22 15:40:58 -05:00
while (this.spawn_timer > pp) {
this.spawn_timer -= pp;
this.spawn();
}
}
// update all particles
2024-09-30 13:06:31 -05:00
for (var p of this.particles) {
2024-07-22 15:40:58 -05:00
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-09-30 13:06:31 -05:00
this.dead.push(p);
this.particles.remove(p);
2024-07-22 15:40:58 -05:00
}
}
2024-09-26 11:36:09 -05:00
};
2024-07-22 15:40:58 -05:00
2024-09-26 11:36:09 -05:00
emitter.burst = function (count, t) {
2024-07-22 15:40:58 -05:00
for (var i = 0; i < count; i++) this.spawn(t);
2024-09-26 11:36:09 -05:00
};
2024-07-22 15:40:58 -05:00
2024-08-25 14:23:22 -05:00
var emitters = [];
2024-09-26 11:36:09 -05:00
var make_emitter = function () {
2024-07-22 15:40:58 -05:00
var e = Object.create(emitter);
e.ssbo = render.make_textssbo();
2024-07-23 17:21:27 -05:00
e.shape = shape.centered_quad;
e.shader = "shaders/baseparticle.cg";
2024-09-30 13:06:31 -05:00
e.particles = [];
e.dead = [];
2024-08-25 14:23:22 -05:00
emitters.push(e);
2024-07-22 15:40:58 -05:00
return e;
2024-09-26 11:36:09 -05:00
};
2024-07-22 15:40:58 -05:00
2024-09-26 11:36:09 -05:00
function update_emitters(dt) {
for (var e of emitters) e.step(dt);
2024-08-25 14:23:22 -05:00
}
2024-09-30 13:06:31 -05:00
var arr = [];
2024-09-26 11:36:09 -05:00
function draw_emitters() {
2024-09-30 11:26:56 -05:00
ssbo ??= render.make_textssbo();
render.use_shader("shaders/baseparticle.cg");
2024-09-30 13:06:31 -05:00
var buckets = {};
2024-09-30 11:26:56 -05:00
var base = 0;
for (var e of emitters) {
2024-09-30 13:06:31 -05:00
var bucket = buckets[e.diffuse.path];
2024-09-30 11:26:56 -05:00
if (!bucket)
2024-09-30 13:06:31 -05:00
buckets[e.diffuse.path] = [e];
2024-09-30 11:26:56 -05:00
else
bucket.push(e);
}
2024-09-30 13:06:31 -05:00
for (var path in buckets) {
arr.length = 0;
var bucket = buckets[path];
2024-09-30 11:26:56 -05:00
bucket[0].baseinstance = base;
render.use_mat(bucket[0]);
2024-09-30 13:06:31 -05:00
for (var e of bucket) {
if (e.particles.length === 0) continue;
for (var p of e.particles) arr.push(p);
}
render.make_particle_ssbo(arr, ssbo);
render.draw(bucket[0].shape, ssbo, arr.length);
base += arr.length;
2024-09-30 11:26:56 -05:00
}
}
function stat_emitters()
{
var stat = {};
stat.emitters = emitters.length;
var particles = 0;
2024-09-30 13:06:31 -05:00
for (var e of emitters) particles += e.particles.length;
stat.particles = particles;
2024-09-30 11:26:56 -05:00
return stat;
2024-08-25 14:23:22 -05:00
}
2024-09-30 11:26:56 -05:00
return { make_emitter, update_emitters, draw_emitters, stat_emitters };