diff --git a/scripts/components.js b/scripts/components.js index 1added1..ad26141 100644 --- a/scripts/components.js +++ b/scripts/components.js @@ -388,10 +388,6 @@ var collider2d = Object.copy(component, { kill() {}, /* No killing is necessary - it is done through the gameobject's kill */ - register_hit(fn, obj) { - register_collide(1, fn, obj, this.gameobject.body, this.shape); - }, - impl: { set sensor(x) { cmd(18,this.shape,x); }, get sensor() { return cmd(21,this.shape); }, diff --git a/scripts/engine.js b/scripts/engine.js index 0c94410..e0537a5 100644 --- a/scripts/engine.js +++ b/scripts/engine.js @@ -217,12 +217,12 @@ register(9, Log.stack, this); Register.gamepad_playermap[0] = Player.players[0]; var Signal = { - obj_begin(fn, obj, go) { - register_collide(0, fn, obj, go.body); + obj_begin(fn, go) { + register_collide(0, fn, go.body); }, - obj_separate(fn, obj, go) { - register_collide(3,fn,obj,go.body); + obj_separate(fn, go) { + register_collide(3,fn, go.body); }, }; diff --git a/scripts/entity.js b/scripts/entity.js index 94520f8..1b4e8ad 100644 --- a/scripts/entity.js +++ b/scripts/entity.js @@ -431,13 +431,13 @@ var gameobject = { obj.timers.push(Register.physupdate.register(obj.physupdate.bind(obj))); if (typeof obj.collide === 'function') - obj.register_hit(obj.collide, obj); + Signal.obj_begin(obj.collide.bind(obj), obj); if (typeof obj.separate === 'function') - obj.register_separate(obj.separate, obj); + Signal.obj_separate(obj.separate.bind(obj), obj); if (typeof obj.draw === 'function') - obj.timers.push(Register.draw.register(obj.draw.bind(obj))); + obj.timers.push(Register.draw.register(obj.draw.bind(obj), obj)); if (typeof obj.debug === 'function') obj.timers.push(Register.debug.register(obj.debug.bind(obj))); @@ -453,7 +453,7 @@ var gameobject = { obj.components.forEach(function(x) { if (typeof x.collide === 'function') - register_collide(1, x.collide, x, obj.body, x.shape); + register_collide(1, x.collide.bind(x), obj.body, x.shape); }); }, toString() { return "new_object"; }, @@ -566,13 +566,14 @@ var gameobject = { this.timers.forEach(t => t()); this.timers = []; + Event.rm_obj(this); + Player.do_uncontrol(this); + register_collide(2, undefined, this.body); if (this.level) { this.level.remove_obj(this); this.level = undefined; } - - Player.do_uncontrol(this); if (this.__proto__.instances) this.__proto__.instances.remove(this); @@ -585,7 +586,7 @@ var gameobject = { this.clear(); this.objects = undefined; - Event.rm_obj(this); + if (typeof this.stop === 'function') this.stop(); @@ -602,9 +603,6 @@ var gameobject = { obj.make = undefined; Object.mixin(obj,gameobject_impl); -// if (this.instances) -// this.instances.push(obj); - obj.body = make_gameobject(); obj.components = {}; @@ -692,16 +690,6 @@ var gameobject = { return this[name]; }, - register_hit(fn, obj) { - obj ??= this; - Signal.obj_begin(fn, obj, this); - }, - - register_separate(fn, obj) { - obj ??= this; - Signal.obj_separate(fn,obj,this); - }, - obj_descend(fn) { fn(this); for (var o in this.objects) diff --git a/source/engine/2dphysics.c b/source/engine/2dphysics.c index ef66abe..cc888eb 100644 --- a/source/engine/2dphysics.c +++ b/source/engine/2dphysics.c @@ -201,10 +201,7 @@ void phys2d_set_gravity(cpVect v) { cpSpaceSetGravity(space, v); } -void phys2d_update(float deltaT) { - cpSpaceStep(space, deltaT); - flush_collide_cbs(); -} +void phys2d_update(float deltaT) { cpSpaceStep(space, deltaT); } void init_phys2dshape(struct phys2d_shape *shape, gameobject *go, void *data) { shape->go = go; @@ -557,96 +554,92 @@ int shape_get_sensor(struct phys2d_shape *shape) { void phys2d_reindex_body(cpBody *body) { cpSpaceReindexShapesForBody(space, body); } -struct postphys_cb { - struct callee c; - JSValue send; -}; - -static struct postphys_cb *begins = NULL; - -void flush_collide_cbs() { - for (int i = 0; i < arrlen(begins); i++) { - script_callee(begins[i].c, 1, &begins[i].send); - JS_FreeValue(js, begins[i].send); - } - - arrsetlen(begins,0); +int arb_valid(cpArbiter *arb) +{ + cpBody *body1; + cpBody *body2; + cpArbiterGetBodies(arb, &body1, &body2); + gameobject *go2 = cpBodyGetUserData(body2); + return !JS_IsUndefined(go2->ref); } -void duk_call_phys_cb(HMM_Vec2 norm, struct callee c, gameobject *hit, cpArbiter *arb) { +JSValue arb2js(cpArbiter *arb) +{ + cpBody *body1; + cpBody *body2; + cpArbiterGetBodies(arb, &body1, &body2); + gameobject *go2 = cpBodyGetUserData(body2); + if (JS_IsUndefined(go2->ref)) return JS_UNDEFINED; cpShape *shape1; cpShape *shape2; cpArbiterGetShapes(arb, &shape1, &shape2); + HMM_Vec2 norm; + norm.cp = cpArbiterGetNormal(arb); + JSValue obj = JS_NewObject(js); JS_SetPropertyStr(js, obj, "normal", vec2js(norm)); - JS_SetPropertyStr(js, obj, "obj", JS_DupValue(js,hit->ref)); + JS_SetPropertyStr(js, obj, "obj", JS_DupValue(js,go2->ref)); JS_SetPropertyStr(js, obj, "sensor", JS_NewBool(js, cpShapeGetSensor(shape2))); + HMM_Vec2 srfv; srfv.cp = cpArbiterGetSurfaceVelocity(arb); JS_SetPropertyStr(js, obj, "velocity", vec2js(srfv)); -// srfv.cp = cpArbiterGetPointA(arb,0); -// JS_SetPropertyStr(js, obj, "pos", vec2js(srfv)); -// JS_SetPropertyStr(js,obj,"depth", num2js(cpArbiterGetDepth(arb,0))); - struct postphys_cb cb; - cb.c = c; - cb.send = obj; - arrput(begins, cb); + return obj; } -#define CTYPE_BEGIN 0 -#define CTYPE_SEP 1 +void phys_run_post(cpSpace *space, JSValue *fn, JSValue *hit) +{ + script_call_fn_arg(*fn, *hit); + JS_FreeValue(js, *hit); +} + +/* TODO: Limitation, cannot handle multiple collision same frame */ +int script_phys_cb_begin(cpArbiter *arb, cpSpace *space, gameobject *go) +{ + if (!arb_valid(arb)) return 1; + + if (!JS_IsUndefined(go->cbs.begin) && cpSpaceAddPostStepCallback(space, phys_run_post, &go->cbs.begin, &go->cbs.bhit)) + go->cbs.bhit = arb2js(arb); -static cpBool handle_collision(cpArbiter *arb, int type) { - cpBody *body1; - cpBody *body2; - cpArbiterGetBodies(arb, &body1, &body2); - gameobject *go = cpBodyGetUserData(body1); - gameobject *go2 = cpBodyGetUserData(body2); cpShape *shape1; cpShape *shape2; cpArbiterGetShapes(arb, &shape1, &shape2); struct phys2d_shape *pshape1 = cpShapeGetUserData(shape1); - struct phys2d_shape *pshape2 = cpShapeGetUserData(shape2); - HMM_Vec2 norm1; - norm1.cp = cpArbiterGetNormal(arb); - - switch (type) { - case CTYPE_BEGIN: - for (int i = 0; i < arrlen(go->shape_cbs); i++) - if (go->shape_cbs[i].shape == pshape1) - duk_call_phys_cb(norm1, go->shape_cbs[i].cbs.begin, go2, arb); - - if (JS_IsObject(go->cbs.begin.obj)) - duk_call_phys_cb(norm1, go->cbs.begin, go2, arb); - - break; - - case CTYPE_SEP: - if (JS_IsObject(go->cbs.separate.obj)) - duk_call_phys_cb(norm1, go->cbs.separate, go2, arb); - - break; + for (int i = 0; i < arrlen(go->shape_cbs); i++) { + if (go->shape_cbs[i].shape != pshape1) continue; + if (!JS_IsUndefined(go->shape_cbs[i].cbs.begin) && cpSpaceAddPostStepCallback(space, phys_run_post, &go->shape_cbs[i].cbs.begin, &go->shape_cbs[i].cbs.bhit)) + go->shape_cbs[i].cbs.bhit = arb2js(arb); } - return 1; } -static cpBool script_phys_cb_begin(cpArbiter *arb, cpSpace *space, void *data) { - return handle_collision(arb, CTYPE_BEGIN); -} - -static cpBool script_phys_cb_separate(cpArbiter *arb, cpSpace *space, void *data) { - return handle_collision(arb, CTYPE_SEP); +void script_phys_cb_separate(cpArbiter *arb, cpSpace *space, gameobject *go) +{ + if (!arb_valid(arb)) return; + if (JS_IsUndefined(go->cbs.separate)) return; + go->cbs.shit = arb2js(arb); + cpSpaceAddPostStepCallback(space, phys_run_post, &go->cbs.separate, &go->cbs.shit); } void phys2d_rm_go_handlers(gameobject *go) { cpCollisionHandler *handler = cpSpaceAddWildcardHandler(space, (cpCollisionType)go); - handler->userData = NULL; - handler->beginFunc = NULL; - handler->separateFunc = NULL; + + if (!JS_IsUndefined(go->cbs.begin)) { + JS_FreeValue(js,go->cbs.begin); + go->cbs.begin = JS_UNDEFINED; + } + if (JS_IsFunction(js,go->cbs.separate)) { + JS_FreeValue(js,go->cbs.separate); + go->cbs.separate = JS_UNDEFINED; + } + + for (int i = 0; i < arrlen(go->shape_cbs); i++) { + JS_FreeValue(js, go->shape_cbs[i].cbs.begin); + go->shape_cbs[i].cbs.begin = JS_UNDEFINED; + } } void phys2d_setup_handlers(gameobject *go) { diff --git a/source/engine/gameobject.c b/source/engine/gameobject.c index 98143a8..fec00d1 100644 --- a/source/engine/gameobject.c +++ b/source/engine/gameobject.c @@ -163,8 +163,8 @@ gameobject *MakeGameobject() { .ref = JS_UNDEFINED, }; - go.cbs.begin.obj = JS_UNDEFINED; - go.cbs.separate.obj = JS_UNDEFINED; + go.cbs.begin = JS_UNDEFINED; + go.cbs.separate = JS_UNDEFINED; go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f)); cpBodySetVelocityUpdateFunc(go.body, velocityFn); @@ -195,41 +195,23 @@ void rm_body_constraints(cpBody *body, cpConstraint *constraint, void *data) cpConstraintFree(constraint); } -gameobject **go_toclean = NULL; - -/* Free this gameobject */ -void gameobject_clean(gameobject *go) { +void gameobject_free(gameobject *go) { arrfree(go->shape_cbs); + go->ref = JS_UNDEFINED; cpBodyEachShape(go->body, rm_body_shapes, NULL); cpBodyEachConstraint(go->body, rm_body_constraints, NULL); cpSpaceRemoveBody(space, go->body); cpBodyFree(go->body); + go->body = NULL; free(go); -} - -/* Really more of a "mark for deletion" ... */ -void gameobject_free(gameobject *go) { - if (!go) return; - - for (int i = arrlen(gameobjects)-1; i >= 0; i--) + for (int i = arrlen(gameobjects)-1; i >= 0; i--) { if (gameobjects[i] == go) { - arrdelswap(gameobjects, i); - break; + arrdelswap(gameobjects,i); + return; } - - if (cpSpaceIsLocked(space)) - arrpush(go_toclean, go); - else - gameobject_clean(go); -} - -void gameobjects_cleanup() { - for (int i = 0; i < arrlen(go_toclean); i++) - gameobject_clean(go_toclean[i]); - - arrsetlen(go_toclean, 0); + } } void gameobject_setangle(gameobject *go, float angle) { diff --git a/source/engine/gameobject.h b/source/engine/gameobject.h index ffef80f..0d5ede8 100644 --- a/source/engine/gameobject.h +++ b/source/engine/gameobject.h @@ -53,7 +53,6 @@ gameobject *MakeGameobject(); int go_count(); void gameobject_apply(gameobject *go); void gameobject_free(gameobject *go); -void gameobjects_cleanup(); transform2d go2t(gameobject *go); transform3d go2t3(gameobject *go); diff --git a/source/engine/jsffi.c b/source/engine/jsffi.c index 28ad541..a910515 100644 --- a/source/engine/jsffi.c +++ b/source/engine/jsffi.c @@ -1506,27 +1506,25 @@ JSValue duk_register(JSContext *js, JSValueConst this, int argc, JSValueConst *a return JS_UNDEFINED; } -void gameobject_add_shape_collider(gameobject *go, struct callee c, struct phys2d_shape *shape) { +void gameobject_add_shape_collider(gameobject *go, JSValue fn, struct phys2d_shape *shape) { struct shape_cb shapecb; shapecb.shape = shape; - shapecb.cbs.begin = c; + shapecb.cbs.begin = fn; arrpush(go->shape_cbs, shapecb); } JSValue duk_register_collide(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { int cmd = js2int(argv[0]); - gameobject *go = js2gameobject(argv[3]); - struct callee c; - c.fn = argv[1]; - c.obj = argv[2]; + gameobject *go = js2gameobject(argv[2]); + JSValue fn = argv[1]; switch (cmd) { case 0: - go->cbs.begin = c; + go->cbs.begin = JS_DupValue(js,fn); break; case 1: - gameobject_add_shape_collider(go, c, js2ptr(argv[4])); + gameobject_add_shape_collider(go, JS_DupValue(js,fn), js2ptr(argv[3])); break; case 2: @@ -1534,7 +1532,7 @@ JSValue duk_register_collide(JSContext *js, JSValueConst this, int argc, JSValue break; case 3: - go->cbs.separate = c; + go->cbs.separate = JS_DupValue(js,fn); break; } diff --git a/source/engine/script.c b/source/engine/script.c index 9161133..fc9cee5 100644 --- a/source/engine/script.c +++ b/source/engine/script.c @@ -254,6 +254,14 @@ void script_call_sym(JSValue sym) { call_callee(&c); } +void script_call_fn_arg(JSValue fn, JSValue arg) +{ + if (!JS_IsFunction(js,fn)) return; + JSValue ret = JS_Call(js, fn, JS_GetGlobalObject(js), 1, &arg); + js_print_exception(ret); + JS_FreeValue(js, ret); +} + void out_memusage(const char *file) { FILE *f = fopen(file, "w"); diff --git a/source/engine/script.h b/source/engine/script.h index c40deb2..21b934e 100644 --- a/source/engine/script.h +++ b/source/engine/script.h @@ -13,9 +13,12 @@ struct callee { }; struct phys_cbs { - struct callee begin; - struct callee separate; + JSValue begin; + JSValue bhit; + JSValue separate; + JSValue shit; }; +void script_call_fn_arg(JSValue fn, JSValue arg); extern struct callee stacktrace_callee; extern JSValue num_cache[100]; diff --git a/source/engine/yugine.c b/source/engine/yugine.c index 3f45a94..176681f 100644 --- a/source/engine/yugine.c +++ b/source/engine/yugine.c @@ -148,8 +148,6 @@ static void process_frame() // prof_start(&prof_draw); window_render(&mainwin); // prof_lap(&prof_draw); - - gameobjects_cleanup(); } void c_frame()