tests; new callbacks

This commit is contained in:
John Alanbrook 2024-01-03 20:26:42 +00:00
parent 7dfd8e6f9a
commit da5b7154d7
11 changed files with 116 additions and 65 deletions

View file

@ -34,4 +34,7 @@ Computation takes place in turns. Each entity has functions called, if they exis
|stop|called when the object is killed|
|debug|use draw functions with the object's world position, during debug pass|
|gui|draw functions in screen space, during gameplay gui pass|
|draw|draw functions in world space|
|draw|draw functions in world space|
## Guidelines
When dealing with callbacks, callback registration can include objects or functions, but not both. You should either register an object to a list that always has 'update' called on them, or you should register the object's update function as a closure over the object.

View file

@ -108,10 +108,6 @@ var Debug = {
cmd(82, obj.body);
},
register_call(fn, obj) {
Register.debug.register(fn,obj);
},
gameobject(go) { cmd(15, go.body); },
draw_bb: false,

View file

@ -191,7 +191,8 @@ var editor = {
Game.play();
Player.players[0].uncontrol(this);
Player.players[0].control(limited_editor);
Register.unregister_obj(this);
editor.cbs.forEach(cb => cb());
editor.cbs = [];
load("predbg.js");
console.warn(`starting game with ${this.dbg_ur}`);
editor.dbg_play = Primum.spawn(this.dbg_ur);
@ -205,18 +206,23 @@ var editor = {
Game.play();
Player.players[0].uncontrol(this);
Player.players[0].control(limited_editor);
Register.unregister_obj(this);
editor.cbs.forEach(cb=>cb());
editor.cbs = [];
load("game.js");
},
cbs: [],
enter_editor() {
Game.pause();
Player.players[0].control(this);
Player.players[0].uncontrol(limited_editor);
Register.gui.register(editor.gui, editor);
Register.draw.register(editor.draw, editor);
Debug.register_call(editor.ed_debug, editor);
Register.update.register(gui_controls.update, gui_controls);
editor.cbs.push(Register.gui.register(editor.gui.bind(editor)));
editor.cbs.push(Register.draw.register(editor.draw.bind(editor)));
editor.cbs.push(Register.debug.register(editor.ed_debug.bind(editor)));
editor.cbs.push(Register.update.register(gui_controls.update, gui_controls));
this.desktop = Primum.spawn(ur.arena);
Primum.rename_obj(this.desktop.toString(), "desktop");
this.edit_level = this.desktop;

View file

@ -81,7 +81,7 @@ var timer = {
},
kill() {
Register.unregister_obj(this);
this.end();
this.fn = undefined;
},
@ -90,7 +90,7 @@ var timer = {
t.time = secs;
t.remain = secs;
t.fn = fn;
Register.update.register(t.update, t);
t.end = Register.update.register(timer.update.bind(t));
return function() { t.kill(); };
},
};
@ -162,12 +162,7 @@ var Register = {
});
},
unregister_obj(obj) {
Register.registries.forEach(function(x) {
x.unregister_obj(obj);
});
Player.uncontrol(obj);
},
unregister_obj(obj) { Player.uncontrol(obj); },
endofloop(fn) {
if (!this.inloop)
@ -186,34 +181,18 @@ var Register = {
registries: [],
add_cb(idx, name) {
var entries = [];
var n = {};
var fns = [];
n.register = function(fn, obj) {
if (!obj) {
Log.error("Refusing to register a function without a destroying object.");
return;
}
entries.push({
fn: fn,
obj: obj
});
}
n.unregister = function(fn) {
entries = entries.filter(function(e) { return e.fn !== fn; });
}
n.unregister_obj = function(obj) {
entries = entries.filter(function(e) { return e.obj !== obj; });
}
n.broadcast = function(...args) {
entries.forEach(x => x.fn.call(x.obj, ...args));
}
n.clear = function() {
entries = [];
if (typeof fn !== 'function') return;
if (typeof obj === 'object')
fn = fn.bind(obj);
fns.push(fn);
return function() { fns.remove(fn); };
}
n.broadcast = function(...args) { fns.forEach(x => x(...args)); }
n.clear = function() { fns = []; }
register(idx, n.broadcast, n);

View file

@ -416,14 +416,19 @@ var gameobject = {
this.sync();
},
unregister() {
this.timers.forEach(t=>t());
this.timers = [];
},
check_registers(obj) {
Register.unregister_obj(obj);
obj.unregister();
if (typeof obj.update === 'function')
Register.update.register(obj.update, obj);
obj.timers.push(Register.update.register(obj.update.bind(obj)));
if (typeof obj.physupdate === 'function')
Register.physupdate.register(obj.physupdate, obj);
obj.timers.push(Register.physupdate.register(obj.physupdate.bind(obj)));
if (typeof obj.collide === 'function')
obj.register_hit(obj.collide, obj);
@ -432,13 +437,13 @@ var gameobject = {
obj.register_separate(obj.separate, obj);
if (typeof obj.draw === 'function')
Register.draw.register(obj.draw,obj);
obj.timers.push(Register.draw.register(obj.draw.bind(obj)));
if (typeof obj.debug === 'function')
Register.debug.register(obj.debug, obj);
obj.timers.push(Register.debug.register(obj.debug.bind(obj)));
if (typeof obj.gui === 'function')
Register.gui.register(obj.gui,obj);
obj.timers.push(Register.gui.register(obj.gui.bind(obj)));
for (var k in obj) {
if (!k.startswith("on_")) continue;
@ -560,7 +565,7 @@ var gameobject = {
this.__kill = true;
this.timers.forEach(t => t());
this.timers = undefined;
this.timers = [];
if (this.level) {
this.level.remove_obj(this);
@ -568,13 +573,11 @@ var gameobject = {
}
Player.do_uncontrol(this);
Register.unregister_obj(this);
if (this.__proto__.instances)
this.__proto__.instances.remove(this);
for (var key in this.components) {
Register.unregister_obj(this.components[key]);
this.components[key].kill();
this.components[key].gameobject = undefined;
delete this.components[key];

View file

@ -173,7 +173,7 @@ var Tween = {
defn.play = function() {
if (playing) return;
Register.update.register(defn.fn, defn);
defn._end = Register.update.register(defn.fn.bind(defn));
playing = true;
};
defn.restart = function() {
@ -185,7 +185,7 @@ var Tween = {
};
defn.stop = function() { if (!playing) return; defn.pause(); defn.restart(); };
defn.pause = function() {
Register.update.unregister(defn.fn);
defn._end();
if (!playing) return;
playing = false;

View file

@ -625,9 +625,9 @@ static cpBool handle_collision(cpArbiter *arb, int type) {
break;
case CTYPE_SEP:
/* if (JS_IsObject(go->cbs.separate.obj))
if (JS_IsObject(go->cbs.separate.obj))
duk_call_phys_cb(norm1, go->cbs.separate, go2, arb);
*/
break;
}

View file

@ -1478,11 +1478,9 @@ JSValue duk_register(JSContext *js, JSValueConst this, int argc, JSValueConst *a
break;
case 4:
// unregister_obj(obj);
break;
case 5:
// unregister_gui(c);
break;
case 6:

View file

@ -155,6 +155,7 @@ static struct par_vert pv[MAX_PARTICLES];
void parallel_pv(emitter *e, struct scheduler *sched, struct sched_task_partition t, sched_uint thread_num)
{
for (int i=t.start; i < t.end; i++) {
if (e->particles[i].life <= 0) continue;
particle *p = &e->particles[i];
pv[i].pos = p->pos.xy;
pv[i].angle = p->angle;
@ -172,7 +173,7 @@ void emitters_draw()
par_bind.fs.images[0] = e->texture->id;
struct sched_task task;
scheduler_add(&sched, &task, parallel_pv, e, arrlen(e->particles), arrlen(e->particles)/SCHED_DEFAULT);
scheduler_add(&sched, &task, parallel_pv, e, arrlen(e->particles), arrlen(e->particles)/sched.threads_num);
scheduler_join(&sched, &task);
sg_append_buffer(par_bind.vertex_buffers[0], &(sg_range){.ptr=&pv, .size=sizeof(struct par_vert)*arrlen(e->particles)});
@ -191,6 +192,7 @@ static HMM_Vec4 g_accel;
void parallel_step(emitter *e, struct scheduler *shed, struct sched_task_partition t, sched_uint thread_num)
{
for (int i = t.end-1; i >=0; i--) {
if (e->particles[i].life <= 0) continue;
if (e->gravity)
e->particles[i].v = HMM_AddV4(e->particles[i].v, g_accel);
e->particles[i].v = HMM_AddV4(e->particles[i].v, HMM_MulV4F((HMM_Vec4){frand(2)-1, frand(2)-1, 0,0}, 1000*dt));
@ -200,10 +202,10 @@ void parallel_step(emitter *e, struct scheduler *shed, struct sched_task_partiti
e->particles[i].color = sample_sampler(&e->color, (e->life-e->particles[i].life)/e->life);
e->particles[i].scale = e->scale;
if (e->particles[i].life <= 0)
arrdelswap(e->particles, i);
else if (query_point(e->particles[i].pos.xy))
arrdelswap(e->particles,i);
// if (e->particles[i].life <= 0)
// arrdelswap(e->particles, i);
// else if (query_point(e->particles[i].pos.xy))
// arrdelswap(e->particles,i);
}
}
@ -212,7 +214,7 @@ void emitter_step(emitter *e, double mdt) {
g_accel = HMM_MulV4F((HMM_Vec4){cpSpaceGetGravity(space).x, cpSpaceGetGravity(space).y, 0, 0}, dt);
if (arrlen(e->particles) == 0) return;
struct sched_task task;
scheduler_add(&sched, &task, parallel_step, e, arrlen(e->particles), arrlen(e->particles));
scheduler_add(&sched, &task, parallel_step, e, arrlen(e->particles), arrlen(e->particles)/sched.threads_num);
scheduler_join(&sched, &task);
if (!e->on) return;

40
tests/bind_v_call.js Normal file
View file

@ -0,0 +1,40 @@
var binds = [];
var cbs = [];
var fats = [];
var count = 1000000;
var a = {
n: 1
}
function test_a() {
this.n++;
}
var start = Date.now();
for (var i = 0; i < count; i++)
binds.push(test_a.bind(a));
console.log(`Make bind time: ${Date.now()-start} ms`);
start = Date.now();
for (var i = 0; i < count; i++)
fats.push(() => test_a.call(a));
console.log(`Make fat time: ${Date.now()-start} ms`);
start = Date.now();
for (var i = 0; i < count; i++) {
binds[i]();
}
console.log(`Bind time: ${Date.now()-start} ms`);
start = Date.now();
for (var i = 0; i < count; i++) {
fats[i]();
}
console.log(`Fat time: ${Date.now()-start} ms`);
start = Date.now();
for (var i = 0; i < count; i++)
test_a.call(a);
console.log(`Call time: ${Date.now()-start} ms`);

24
tests/bind_v_fn.js Normal file
View file

@ -0,0 +1,24 @@
var binds = [];
var a = {
n: 1,
test() { this.n++; }
};
var count = 10000000;
var start = Date.now();
for (var i = 0; i < count; i++)
binds.push(a.test.bind(a));
console.log(`Make bind time: ${Date.now()-start} ms`);
start = Date.now();
for (var i = 0; i < count; i++)
binds[i]();
console.log(`Bind time: ${Date.now()-start} ms`);
start = Date.now();
for (var i = 0; i < count; i++)
a['test']();
console.log(`Call time: ${Date.now()-start} ms`);