fix collisions
This commit is contained in:
parent
da5b7154d7
commit
913c74db96
|
@ -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); },
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -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,14 +566,15 @@ 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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -148,8 +148,6 @@ static void process_frame()
|
|||
// prof_start(&prof_draw);
|
||||
window_render(&mainwin);
|
||||
// prof_lap(&prof_draw);
|
||||
|
||||
gameobjects_cleanup();
|
||||
}
|
||||
|
||||
void c_frame()
|
||||
|
|
Loading…
Reference in a new issue