From a3428f0d36ab1a40589031f95bf960610673bab7 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Fri, 24 Feb 2023 18:11:36 +0000 Subject: [PATCH] Add MOI calculations for gameobject sync --- source/engine/2dphysics.c | 42 ++++++++++++++++++++++++++++++++++---- source/engine/2dphysics.h | 6 ++++++ source/engine/ffi.c | 12 ++++++++--- source/engine/gameobject.c | 15 ++++++++++++-- source/engine/script.c | 15 ++++++++++++++ source/engine/script.h | 1 + 6 files changed, 82 insertions(+), 9 deletions(-) diff --git a/source/engine/2dphysics.c b/source/engine/2dphysics.c index 8158b1d..80248b8 100644 --- a/source/engine/2dphysics.c +++ b/source/engine/2dphysics.c @@ -192,11 +192,17 @@ struct phys2d_circle *Make2DCircle(int go) new->shape.shape = cpSpaceAddShape(space, cpCircleShapeNew(id2go(go)->body, new->radius, cpvzero)); new->shape.debugdraw = phys2d_dbgdrawcircle; + new->shape.moi = phys2d_circle_moi; init_phys2dshape(&new->shape, go, new); return new; } +float phys2d_circle_moi(struct phys2d_circle *c, float m) +{ + return cpMomentForCircle(m, 0, c->radius, c->offset); +} + void phys2d_circledel(struct phys2d_circle *c) { phys2d_shape_del(&c->shape); @@ -288,10 +294,16 @@ struct phys2d_box *Make2DBox(int go) new->shape.go = go; phys2d_applybox(new); new->shape.debugdraw = phys2d_dbgdrawbox; + new->shape.moi = phys2d_box_moi; return new; } +float phys2d_box_moi(struct phys2d_box *box, float m) +{ + return cpMomentForBox(m, box->w, box->h); +} + cpTransform go2transform(struct gameobject *go, cpVect offset, float angle) { cpTransform T = {0}; @@ -346,10 +358,16 @@ struct phys2d_poly *Make2DPoly(int go) new->shape.shape = cpSpaceAddShape(space, cpPolyShapeNewRaw(id2go(go)->body, 0, new->points, new->radius)); new->shape.debugdraw = phys2d_dbgdrawpoly; + new->shape.moi = phys2d_poly_moi; init_phys2dshape(&new->shape, go, new); return new; } +float phys2d_poly_moi(struct phys2d_poly *poly, float m) +{ + return cpMomentForPoly(m, arrlen(poly->points), poly->points, cpvzero, poly->radius); +} + void phys2d_polydel(struct phys2d_poly *poly) { arrfree(poly->points); @@ -409,12 +427,18 @@ struct phys2d_edge *Make2DEdge(int go) new->shape.go = go; new->shape.data = new; new->shape.debugdraw = phys2d_dbgdrawedge; + new->shape.moi = phys2d_edge_moi; new->shape.shape = NULL; phys2d_applyedge(new); return new; } +float phys2d_edge_moi(struct phys2d_edge *edge, float m) +{ + return m; +} + void phys2d_edgedel(struct phys2d_edge *edge) { phys2d_shape_del(&edge->shape); @@ -585,8 +609,9 @@ void duk_call_phys_cb(cpArbiter *arb, struct callee c, int hit) duk_pop(duk); } -static cpBool script_phys_cb_begin(cpArbiter *arb, cpSpace *space, void *data) { - +static cpBool script_phys_cb_begin(cpArbiter *arb, cpSpace *space, void *data) +{ + cpBody *body1; cpBody *body2; cpArbiterGetBodies(arb, &body1, &body2); @@ -602,12 +627,21 @@ static cpBool script_phys_cb_begin(cpArbiter *arb, cpSpace *space, void *data) { for (int i = 0; i < arrlen(go->shape_cbs); i++) { duk_call_phys_cb(arb, go->shape_cbs[i].cbs.begin, g2); } - - duk_call_phys_cb(arb, go->cbs.begin, g2); + + if (go->cbs.begin.obj) + duk_call_phys_cb(arb, go->cbs.begin, g2); return 1; } +void phys2d_rm_go_handlers(int go) +{ + cpCollisionHandler *handler = cpSpaceAddWildcardHandler(space, go); + handler->userData = NULL; + handler->beginFunc = NULL; + handler->separateFunc = NULL; +} + void phys2d_add_handler_type(int cmd, int go, struct callee c) { cpCollisionHandler *handler = cpSpaceAddWildcardHandler(space, go); diff --git a/source/engine/2dphysics.h b/source/engine/2dphysics.h index 7d12577..5064129 100644 --- a/source/engine/2dphysics.h +++ b/source/engine/2dphysics.h @@ -20,6 +20,7 @@ struct phys2d_shape { int go; void *data; void (*debugdraw)(void *data); + float (*moi)(void *data, float mass); }; /* Circles are the fastest collier type */ @@ -68,11 +69,13 @@ struct phys2d_circle *Make2DCircle(int go); void phys2d_circledel(struct phys2d_circle *c); void phys2d_applycircle(struct phys2d_circle *circle); void phys2d_dbgdrawcircle(struct phys2d_circle *circle); +float phys2d_circle_moi(struct phys2d_circle *c, float m); struct phys2d_box *Make2DBox(int go); void phys2d_boxdel(struct phys2d_box *box); void phys2d_applybox(struct phys2d_box *box); void phys2d_dbgdrawbox(struct phys2d_box *box); +float phys2d_box_moi(struct phys2d_box *box, float m); struct phys2d_poly *Make2DPoly(int go); void phys2d_polydel(struct phys2d_poly *poly); @@ -80,6 +83,7 @@ void phys2d_applypoly(struct phys2d_poly *poly); void phys2d_dbgdrawpoly(struct phys2d_poly *poly); void phys2d_polyaddvert(struct phys2d_poly *poly); void phys2d_poly_setverts(struct phys2d_poly *poly, cpVect *verts); +float phys2d_poly_moi(struct phys2d_poly *poly, float m); struct phys2d_edge *Make2DEdge(int go); void phys2d_edgedel(struct phys2d_edge *edge); @@ -87,6 +91,7 @@ void phys2d_applyedge(struct phys2d_edge *edge); void phys2d_dbgdrawedge(struct phys2d_edge *edge); void phys2d_edgeaddvert(struct phys2d_edge *edge); void phys2d_edge_rmvert(struct phys2d_edge *edge, int index); +float phys2d_edge_moi(struct phys2d_edge *edge, float m); void phys2d_edge_setvert(struct phys2d_edge *edge, int index, cpVect val); void phys2d_edge_clearverts(struct phys2d_edge *edge); @@ -111,6 +116,7 @@ struct shape_cb { void phys2d_add_handler_type(int cmd, int go, struct callee c); void register_collide(void *sym); +void phys2d_rm_go_handlers(int go); void phys2d_set_gravity(cpVect v); void shape_enabled(struct phys2d_shape *shape, int enabled); diff --git a/source/engine/ffi.c b/source/engine/ffi.c index 14879b4..7665532 100644 --- a/source/engine/ffi.c +++ b/source/engine/ffi.c @@ -659,12 +659,10 @@ duk_ret_t duk_cmd(duk_context *duk) { case 55: duk2go(duk, 1)->flipx = duk_to_boolean(duk, 2) ? -1 : 1; - gameobject_apply(duk2go(duk, 1)); return 0; case 56: duk2go(duk, 1)->flipy = duk_to_boolean(duk, 2) ? -1 : 1; - gameobject_apply(duk2go(duk, 1)); return 0; case 57: @@ -767,6 +765,11 @@ duk_ret_t duk_register(duk_context *duk) { case 3: register_nk_gui(c); break; + + case 4: + unregister_obj(obj); + break; + } return 0; @@ -795,6 +798,9 @@ duk_ret_t duk_register_collide(duk_context *duk) { case 1: gameobject_add_shape_collider(go, c, duk_get_pointer(duk,4)); break; + + case 2: + phys2d_rm_go_handlers(go); } return 0; @@ -892,7 +898,7 @@ duk_ret_t duk_set_body(duk_context *duk) { break; case 1: - cpBodySetType(go->body, duk_to_int(duk, 2)); + go->bodytype = duk_to_int(duk,2); break; case 2: diff --git a/source/engine/gameobject.c b/source/engine/gameobject.c index 1248a70..d8fbd10 100644 --- a/source/engine/gameobject.c +++ b/source/engine/gameobject.c @@ -97,17 +97,28 @@ void go_shape_apply(cpBody *body, cpShape *shape, struct gameobject *go) cpShapeSetElasticity(shape, go->e); cpShapeSetSensor(shape, go->sensor); cpShapeSetCollisionType(shape, go2id(go)); + + float moment = cpBodyGetMoment(go->body); + struct phys2d_shape *s = cpShapeGetUserData(shape); + if (!s) { + cpBodySetMoment(go->body, moment+1); + return; + } + + moment += s->moi(s->data, go->mass); + cpBodySetMoment(go->body, moment); // cpShapeSetFilter(shape, go->filter); } void gameobject_apply(struct gameobject *go) { cpBodySetType(go->body, go->bodytype); - + cpBodySetMoment(go->body, 0.f); + cpBodyEachShape(go->body, go_shape_apply, go); if (go->bodytype == CP_BODY_TYPE_DYNAMIC) cpBodySetMass(go->body, go->mass); + - cpBodyEachShape(go->body, go_shape_apply, go); } static void gameobject_setpickcolor(struct gameobject *go) diff --git a/source/engine/script.c b/source/engine/script.c index a55fa71..8361f87 100644 --- a/source/engine/script.c +++ b/source/engine/script.c @@ -156,6 +156,21 @@ struct callee *physics = NULL; struct callee *guis = NULL; struct callee *nk_guis = NULL; +void unregister_obj(void *obj) +{ + for (int i = arrlen(updates)-1; i >= 0; i--) + if (updates[i].obj == obj) arrdel(updates, i); + + for (int i = arrlen(physics)-1; i >= 0; i--) + if (physics[i].obj == obj) arrdel(physics,i); + + for (int i = arrlen(guis)-1; i >= 0; i--) + if (guis[i].obj == obj) arrdel(guis,i); + + for (int i = arrlen(nk_guis)-1; i >= 0; i--) + if (guis[i].obj == obj) arrdel(nk_guis,i); +} + void register_update(struct callee c) { arrput(updates, c); } diff --git a/source/engine/script.h b/source/engine/script.h index 49d893c..acfdaa4 100644 --- a/source/engine/script.h +++ b/source/engine/script.h @@ -40,6 +40,7 @@ void register_gui(struct callee c); void register_nk_gui(struct callee c); void call_gui(); void call_nk_gui(); +void unregister_obj(void *obj); void register_physics(struct callee c); void call_physics(double dt);