Add MOI calculations for gameobject sync

This commit is contained in:
John Alanbrook 2023-02-24 18:11:36 +00:00
parent a613e19ffa
commit a3428f0d36
6 changed files with 82 additions and 9 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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:

View file

@ -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)

View file

@ -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);
}

View file

@ -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);