From 9fb36f5df3714ba04cad1bdc35e377b23a11cb26 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Mon, 11 Dec 2023 14:36:45 +0000 Subject: [PATCH] spline --- scripts/entity.js | 14 +- source/engine/2dphysics.c | 73 ++++---- source/engine/2dphysics.h | 25 ++- source/engine/3d/model.c | 2 +- source/engine/3d/model.h | 3 +- source/engine/gameobject.c | 153 ++++++----------- source/engine/gameobject.h | 63 ++++--- source/engine/jsffi.c | 178 ++++++++------------ source/engine/level.c | 49 ------ source/engine/level.h | 16 -- source/engine/render.c | 5 +- source/engine/script.h | 6 + source/engine/spline.c | 334 +++++++++++++++++++++++++++++++++++++ source/engine/spline.h | 22 +++ source/engine/sprite.c | 6 +- source/engine/sprite.h | 6 +- source/engine/yugine.c | 32 +--- 17 files changed, 580 insertions(+), 407 deletions(-) delete mode 100644 source/engine/level.c delete mode 100644 source/engine/level.h create mode 100644 source/engine/spline.c create mode 100644 source/engine/spline.h diff --git a/scripts/entity.js b/scripts/entity.js index 61cd15a..c61b99f 100644 --- a/scripts/entity.js +++ b/scripts/entity.js @@ -141,8 +141,7 @@ var gameobject = { this.set_worldpos(this.level.this2world(x)); }, - get pos() { return cmd - + get pos() { if (!this.level) return this.worldpos(); return this.level.world2this(this.worldpos()); }, @@ -238,7 +237,8 @@ var gameobject = { this.level?.remove_obj(this); this.level = parent; - cmd(208,parent,this); + + cmd(208,parent.body,this.body); function unique_name(list, obj) { var str = obj.toString().replaceAll('.', '_'); @@ -310,13 +310,9 @@ var gameobject = { return bb.t-bb.b; }, - move(vec) { - this.pos = this.pos.add(vec); - }, + move(vec) { this.pos = this.pos.add(vec); }, - rotate(amt) { - this.angle += amt; - }, + rotate(amt) { this.angle += amt; }, /* Make a unique object the same as its prototype */ revert() { diff --git a/source/engine/2dphysics.c b/source/engine/2dphysics.c index f67c0e9..906bcf9 100644 --- a/source/engine/2dphysics.c +++ b/source/engine/2dphysics.c @@ -33,9 +33,7 @@ static const float sensor_seg = 10; unsigned int category_masks[32]; -void set_cat_mask(int cat, unsigned int mask) { - category_masks[cat] = mask; -} +void set_cat_mask(int cat, unsigned int mask) { category_masks[cat] = mask; } cpTransform m3_to_cpt(HMM_Mat3 m) { @@ -66,7 +64,7 @@ int sort_ids(int *a, int *b) return 1; } -int *clean_ids(int *ids) +gameobject *clean_ids(int *ids) { qsort(ids, sizeof(*ids), arrlen(ids), sort_ids); @@ -80,18 +78,16 @@ int *clean_ids(int *ids) return ids; } -void querylist(cpShape *shape, cpContactPointSet *points, int *ids) { - arrput(ids,shape2gameobject(shape)); -} +void querylist(cpShape *shape, cpContactPointSet *points, int *ids) { arrput(ids,shape2go(shape)); } typedef struct querybox { cpBB bb; - int *ids; + gameobject **ids; } querybox; void querylistbodies(cpBody *body, querybox *qb) { if (cpBBContainsVect(qb->bb, cpBodyGetPosition(body))) - arrput(qb->ids,body2id(body)); + arrput(qb->ids,body2go(body)); } /* Return all points from a list of points in the given boundingbox */ @@ -109,7 +105,7 @@ int *phys2d_query_box_points(HMM_Vec2 pos, HMM_Vec2 wh, HMM_Vec2 *points, int n) } /* Return all gameobjects within the given box */ -int *phys2d_query_box(HMM_Vec2 pos, HMM_Vec2 wh) { +gameobject *phys2d_query_box(HMM_Vec2 pos, HMM_Vec2 wh) { cpShape *box = cpBoxShapeNew(NULL, wh.x, wh.y, 0.f); cpTransform T = {0}; T.a = 1; @@ -134,8 +130,8 @@ int *phys2d_query_box(HMM_Vec2 pos, HMM_Vec2 wh) { return clean_ids(ids); } -int *phys2d_query_shape(struct phys2d_shape *shape) { - int *ids = NULL; +gameobject *phys2d_query_shape(struct phys2d_shape *shape) { + gameobject **ids = NULL; cpSpaceShapeQuery(space, shape->shape, querylist, ids); return clean_ids(ids); } @@ -184,10 +180,10 @@ void phys2d_update(float deltaT) { flush_collide_cbs(); } -void init_phys2dshape(struct phys2d_shape *shape, int go, void *data) { +void init_phys2dshape(struct phys2d_shape *shape, gameobject *go, void *data) { shape->go = go; shape->data = data; - go_shape_apply(id2go(go)->body, shape->shape, id2go(go)); + go_shape_apply(go->body, shape->shape, go); cpShapeSetCollisionType(shape->shape, go); cpShapeSetUserData(shape->shape, shape); } @@ -199,13 +195,13 @@ void phys2d_shape_del(struct phys2d_shape *shape) { } /***************** CIRCLE2D *****************/ -struct phys2d_circle *Make2DCircle(int go) { +struct phys2d_circle *Make2DCircle(gameobject *go) { struct phys2d_circle *new = malloc(sizeof(struct phys2d_circle)); new->radius = 10.f; new->offset = v2zero; - new->shape.shape = cpSpaceAddShape(space, cpCircleShapeNew(id2go(go)->body, new->radius, cpvzero)); + new->shape.shape = cpSpaceAddShape(space, cpCircleShapeNew(go->body, new->radius, cpvzero)); new->shape.debugdraw = phys2d_dbgdrawcircle; new->shape.moi = phys2d_circle_moi; new->shape.apply = phys2d_applycircle; @@ -240,7 +236,7 @@ void phys2d_dbgdrawcircle(struct phys2d_circle *circle) { } void phys2d_applycircle(struct phys2d_circle *circle) { - struct gameobject *go = id2go(circle->shape.go); + gameobject *go = circle->shape.go; float radius = circle->radius * HMM_MAX(HMM_ABS(go->scale.X), HMM_ABS(go->scale.Y)); cpCircleShapeSetRadius(circle->shape.shape, radius); @@ -250,7 +246,7 @@ void phys2d_applycircle(struct phys2d_circle *circle) { /************* BOX2D ************/ -struct phys2d_box *Make2DBox(int go) { +struct phys2d_box *Make2DBox(gameobject *go) { struct phys2d_box *new = malloc(sizeof(struct phys2d_box)); new->t = (transform2d){ .pos = {0,0}, @@ -277,7 +273,7 @@ void phys2d_boxdel(struct phys2d_box *box) { void phys2d_applybox(struct phys2d_box *box) { phys2d_boxdel(box); - struct gameobject *go = id2go(box->shape.go); + struct gameobject *go = box->shape.go; cpTransform T = m3_to_cpt(transform2d2mat(box->t)); cpVect verts[4] = {{-0.5, -0.5}, {0.5, -0.5}, {0.5, 0.5}, {-0.5, 0.5}}; box->shape.shape = cpSpaceAddShape(space, cpPolyShapeNew(go->body, 4, verts, T, box->r)); @@ -304,14 +300,14 @@ void phys2d_dbgdrawbox(struct phys2d_box *box) { } /************** POLYGON ************/ -struct phys2d_poly *Make2DPoly(int go) { +struct phys2d_poly *Make2DPoly(gameobject *go) { struct phys2d_poly *new = malloc(sizeof(struct phys2d_poly)); new->points = NULL; arrsetlen(new->points, 0); new->radius = 0.f; - new->shape.shape = cpSpaceAddShape(space, cpPolyShapeNewRaw(id2go(go)->body, 0, new->points, new->radius)); + new->shape.shape = cpSpaceAddShape(space, cpPolyShapeNewRaw(go->body, 0, new->points, new->radius)); new->shape.debugdraw = phys2d_dbgdrawpoly; new->shape.moi = phys2d_poly_moi; new->shape.apply = phys2d_applypoly; @@ -354,7 +350,7 @@ void phys2d_poly_setverts(struct phys2d_poly *poly, cpVect *verts) { void phys2d_applypoly(struct phys2d_poly *poly) { if (arrlen(poly->points) <= 0) return; - struct gameobject *go = id2go(poly->shape.go); + struct gameobject *go = poly->shape.go; cpTransform T = m3_to_cpt(transform2d2mat(poly->t)); cpPolyShapeSetVerts(poly->shape.shape, arrlen(poly->points), poly->points, T); cpPolyShapeSetRadius(poly->shape.shape, poly->radius); @@ -379,7 +375,7 @@ void phys2d_dbgdrawpoly(struct phys2d_poly *poly) { } /****************** EDGE 2D**************/ -struct phys2d_edge *Make2DEdge(int go) { +struct phys2d_edge *Make2DEdge(gameobject *go) { struct phys2d_edge *new = malloc(sizeof(struct phys2d_edge)); new->points = NULL; arrsetlen(new->points, 0); @@ -414,7 +410,7 @@ void phys2d_edgedel(struct phys2d_edge *edge) { void phys2d_edgeaddvert(struct phys2d_edge *edge) { arrput(edge->points, v2zero); if (arrlen(edge->points) > 1) - arrput(edge->shapes, cpSpaceAddShape(space, cpSegmentShapeNew(id2go(edge->shape.go)->body, cpvzero, cpvzero, edge->thickness))); + arrput(edge->shapes, cpSpaceAddShape(space, cpSegmentShapeNew(edge->shape.go->body, cpvzero, cpvzero, edge->thickness))); phys2d_applyedge(edge); } @@ -466,7 +462,7 @@ void phys2d_edge_addverts(struct phys2d_edge *edge, cpVect *verts) { } void phys2d_applyedge(struct phys2d_edge *edge) { - struct gameobject *go = id2go(edge->shape.go); + struct gameobject *go = edge->shape.go; for (int i = 0; i < arrlen(edge->shapes); i++) { /* Points must be scaled with gameobject, */ @@ -480,7 +476,7 @@ void phys2d_applyedge(struct phys2d_edge *edge) { cpShapeSetUserData(edge->shapes[i], &edge->shape); } - cpSpaceReindexShapesForBody(space, id2go(edge->shape.go)->body); + cpSpaceReindexShapesForBody(space, edge->shape.go->body); } void phys2d_dbgdrawedge(struct phys2d_edge *edge) { @@ -495,7 +491,7 @@ void phys2d_dbgdrawedge(struct phys2d_edge *edge) { if (arrlen(edge->shapes) < 1) return; HMM_Vec2 drawpoints[arrlen(edge->points)]; - struct gameobject *go = id2go(edge->shape.go); + struct gameobject *go = edge->shape.go; HMM_Mat3 g2w = t_go2world(go); for (int i = 0; i < arrlen(edge->points); i++) @@ -563,7 +559,7 @@ void flush_collide_cbs() { arrsetlen(begins,0); } -void duk_call_phys_cb(HMM_Vec2 norm, struct callee c, int hit, cpArbiter *arb) { +void duk_call_phys_cb(HMM_Vec2 norm, struct callee c, gameobject *hit, cpArbiter *arb) { cpShape *shape1; cpShape *shape2; cpArbiterGetShapes(arb, &shape1, &shape2); @@ -579,7 +575,7 @@ void duk_call_phys_cb(HMM_Vec2 norm, struct callee c, int hit, cpArbiter *arb) { // JS_SetPropertyStr(js, obj, "pos", vec2js(srfv)); // JS_SetPropertyStr(js,obj,"depth", num2js(cpArbiterGetDepth(arb,0))); JS_SetPropertyStr(js, obj, "id", JS_NewInt32(js,hit)); - JS_SetPropertyStr(js,obj,"obj", JS_DupValue(js,id2go(hit)->ref)); + JS_SetPropertyStr(js,obj,"obj", JS_DupValue(js,hit->ref)); struct postphys_cb cb; cb.c = c; @@ -594,11 +590,8 @@ static cpBool handle_collision(cpArbiter *arb, int type) { cpBody *body1; cpBody *body2; cpArbiterGetBodies(arb, &body1, &body2); - int g1 = (int)cpBodyGetUserData(body1); - int g2 = (int)cpBodyGetUserData(body2); - struct gameobject *go = id2go(g1); - struct gameobject *go2 = id2go(g2); - + gameobject *go = cpBodyGetUserData(body1); + gameobject *go2 = cpBodyGetUserData(body2); cpShape *shape1; cpShape *shape2; cpArbiterGetShapes(arb, &shape1, &shape2); @@ -612,16 +605,16 @@ static cpBool handle_collision(cpArbiter *arb, int 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, g2, arb); + 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, g2, arb); + 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, g2, arb); + duk_call_phys_cb(norm1, go->cbs.separate, go2, arb); break; } @@ -637,16 +630,16 @@ static cpBool script_phys_cb_separate(cpArbiter *arb, cpSpace *space, void *data return handle_collision(arb, CTYPE_SEP); } -void phys2d_rm_go_handlers(int go) { +void phys2d_rm_go_handlers(gameobject *go) { cpCollisionHandler *handler = cpSpaceAddWildcardHandler(space, go); handler->userData = NULL; handler->beginFunc = NULL; handler->separateFunc = NULL; } -void phys2d_setup_handlers(int go) { +void phys2d_setup_handlers(gameobject *go) { cpCollisionHandler *handler = cpSpaceAddWildcardHandler(space, go); - handler->userData = (void *)go; + handler->userData = go; handler->beginFunc = script_phys_cb_begin; handler->separateFunc = script_phys_cb_separate; } diff --git a/source/engine/2dphysics.h b/source/engine/2dphysics.h index 5f48650..03230f4 100644 --- a/source/engine/2dphysics.h +++ b/source/engine/2dphysics.h @@ -3,11 +3,10 @@ #include "script.h" #include +#include "gameobject.h" #include "render.h" #include "transform.h" -struct gameobject; - extern float phys2d_gravity; extern int physOn; extern cpSpace *space; @@ -24,7 +23,7 @@ extern struct rgba sleep_color; struct phys2d_shape { cpShape *shape; transform2d t; - int go; + gameobject *go; void *data; /* The specific subtype; phys2d_circle, etc */ void (*debugdraw)(void *data); float (*moi)(void *data, float mass); @@ -71,19 +70,19 @@ struct phys2d_edge { int draws; }; -struct phys2d_circle *Make2DCircle(int go); +struct phys2d_circle *Make2DCircle(gameobject *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); +struct phys2d_box *Make2DBox(gameobject *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); +struct phys2d_poly *Make2DPoly(gameobject *go); void phys2d_polydel(struct phys2d_poly *poly); void phys2d_applypoly(struct phys2d_poly *poly); void phys2d_dbgdrawpoly(struct phys2d_poly *poly); @@ -91,7 +90,7 @@ 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); +struct phys2d_edge *Make2DEdge(gameobject *go); void phys2d_edgedel(struct phys2d_edge *edge); void phys2d_applyedge(struct phys2d_edge *edge); void phys2d_dbgdrawedge(struct phys2d_edge *edge); @@ -108,12 +107,8 @@ void phys2d_edge_set_enabled(struct phys2d_edge *edge, int enabled); void phys2d_init(); void phys2d_update(float deltaT); cpShape *phys2d_query_pos(cpVect pos); -int *phys2d_query_box(HMM_Vec2 pos, HMM_Vec2 wh); +gameobject *phys2d_query_box(HMM_Vec2 pos, HMM_Vec2 wh); -struct phys_cbs { - struct callee begin; - struct callee separate; -}; struct shape_cb { struct phys2d_shape *shape; @@ -122,7 +117,7 @@ struct shape_cb { void fire_hits(); -void phys2d_rm_go_handlers(int go); +void phys2d_rm_go_handlers(gameobject *go); void phys2d_set_gravity(cpVect v); void shape_enabled(struct phys2d_shape *shape, int enabled); @@ -133,8 +128,8 @@ int shape_get_sensor(struct phys2d_shape *shape); struct rgba shape_color_s(cpShape *shape); void shape_gui(struct phys2d_shape *shape); -void phys2d_setup_handlers(int go); -int *phys2d_query_shape(struct phys2d_shape *shape); +void phys2d_setup_handlers(gameobject *go); +gameobject *phys2d_query_shape(struct phys2d_shape *shape); int *phys2d_query_box_points(HMM_Vec2 pos, HMM_Vec2 wh, HMM_Vec2 *points, int n); void flush_collide_cbs(); diff --git a/source/engine/3d/model.c b/source/engine/3d/model.c index 2865ebc..31c3b5a 100644 --- a/source/engine/3d/model.c +++ b/source/engine/3d/model.c @@ -390,7 +390,7 @@ struct drawmodel *make_drawmodel(int go) void draw_drawmodel(struct drawmodel *dm) { if (!dm->model) return; - struct gameobject *go = id2go(dm->go); + struct gameobject *go = dm->go; HMM_Mat4 rst = t3d_go2world(go); draw_model(dm->model, rst); } diff --git a/source/engine/3d/model.h b/source/engine/3d/model.h index fb9ca57..1eaa605 100644 --- a/source/engine/3d/model.h +++ b/source/engine/3d/model.h @@ -4,6 +4,7 @@ #include "HandmadeMath.h" #include "transform.h" #include "sokol/sokol_gfx.h" +#include "gameobject.h" extern HMM_Vec3 eye; struct shader; @@ -32,7 +33,7 @@ typedef struct model { struct drawmodel { struct model *model; HMM_Mat4 amodel; - int go; + gameobject *go; }; typedef struct bone { diff --git a/source/engine/gameobject.c b/source/engine/gameobject.c index 1f02db0..461b727 100644 --- a/source/engine/gameobject.c +++ b/source/engine/gameobject.c @@ -1,61 +1,35 @@ #include "gameobject.h" #include "2dphysics.h" -#include "log.h" #include #include #include "debugdraw.h" -#include "freelist.h" +#include "log.h" #include "stb_ds.h" -struct gameobject *gameobjects = NULL; - -struct gameobject *id2go(int id) { - if (id < 0) return NULL; - - return &gameobjects[id]; -} - -int body2id(cpBody *body) { return (int)cpBodyGetUserData(body); } - -cpBody *id2body(int id) { - struct gameobject *go = id2go(id); - - if (go) - return go->body; - - return NULL; -} - -int shape2gameobject(cpShape *shape) { - struct phys2d_shape *s = cpShapeGetUserData(shape); - return s->go; -} - -struct gameobject *shape2go(cpShape *shape) +gameobject *body2go(cpBody *body) { return cpBodyGetUserData(body); } +gameobject *shape2go(cpShape *shape) { - return id2go(shape2gameobject(shape)); + return ((struct phys2d_shape *)cpShapeGetUserData(shape))->go; } -HMM_Vec2 go_pos(struct gameobject *go) +HMM_Vec2 go_pos(gameobject *go) { cpVect p = cpBodyGetPosition(go->body); return (HMM_Vec2){p.x, p.y}; } -HMM_Vec2 go_worldpos(struct gameobject *go) +HMM_Vec2 go_worldpos(gameobject *go) { HMM_Vec2 ret; ret.cp = cpBodyGetPosition(go->body); return ret; } -float go_angle(struct gameobject *go) { return go_worldangle(go); } - -float go_worldangle(struct gameobject *go) { return cpBodyGetAngle(go->body); } - -float go2angle(struct gameobject *go) { return cpBodyGetAngle(go->body); } +float go_angle(gameobject *go) { return go_worldangle(go); } +float go_worldangle(gameobject *go) { return cpBodyGetAngle(go->body); } +float go2angle(gameobject *go) { return cpBodyGetAngle(go->body); } transform3d go2t3(gameobject *go) { @@ -72,23 +46,21 @@ transform3d go2t3(gameobject *go) return t; } -HMM_Vec2 go2world(struct gameobject *go, HMM_Vec2 pos) { return mat_t_pos(t_go2world(go), pos); } +HMM_Vec2 go2world(gameobject *go, HMM_Vec2 pos) { return mat_t_pos(t_go2world(go), pos); } +HMM_Vec2 world2go(gameobject *go, HMM_Vec2 pos) { return mat_t_pos(t_world2go(go), pos); } +HMM_Mat3 t_go2world(gameobject *go) { return transform2d2mat(go2t(go)); } +HMM_Mat3 t_world2go(gameobject *go) { return HMM_InvGeneralM3(t_go2world(go)); } +HMM_Mat4 t3d_go2world(gameobject *go) { return transform3d2mat(go2t3(go)); } +HMM_Mat4 t3d_world2go(gameobject *go) { return HMM_InvGeneralM4(t3d_go2world(go)); } -HMM_Vec2 world2go(struct gameobject *go, HMM_Vec2 pos) { return mat_t_pos(t_world2go(go), pos); } - -HMM_Mat3 t_go2world(struct gameobject *go) { return transform2d2mat(go2t(go)); } - -HMM_Mat3 t_world2go(struct gameobject *go) { return HMM_InvGeneralM3(t_go2world(go)); } - -HMM_Mat4 t3d_go2world(struct gameobject *go) { return transform3d2mat(go2t3(go)); } -HMM_Mat4 t3d_world2go(struct gameobject *go) { return HMM_InvGeneralM4(t3d_go2world(go)); } - -int pos2gameobject(HMM_Vec2 pos) { +gameobject *pos2gameobject(HMM_Vec2 pos) { cpShape *hit = phys2d_query_pos(pos.cp); if (hit) - return shape2gameobject(hit); + return shape2go(hit); + return NULL; +/* for (int i = 0; i < arrlen(gameobjects); i++) { if (!gameobjects[i].body) continue; cpVect gpos = cpBodyGetPosition(gameobjects[i].body); @@ -96,8 +68,8 @@ int pos2gameobject(HMM_Vec2 pos) { if (dist <= 25) return i; } - - return -1; + */ + return NULL; } transform2d go2t(gameobject *go) @@ -111,22 +83,15 @@ transform2d go2t(gameobject *go) return t; } -int go2id(struct gameobject *go) { - for (int i = 0; i < arrlen(gameobjects); i++) - if (&gameobjects[i] == go) return i; - - return -1; -} - unsigned int editor_cat = 1<<31; -void go_shape_apply(cpBody *body, cpShape *shape, struct gameobject *go) { +void go_shape_apply(cpBody *body, cpShape *shape, gameobject *go) { cpShapeSetFriction(shape, go->f); cpShapeSetElasticity(shape, go->e); - cpShapeSetCollisionType(shape, go2id(go)); + cpShapeSetCollisionType(shape, go); cpShapeFilter filter; - filter.group = go2id(go); + filter.group = go; filter.categories = 1<layer | editor_cat; // filter.mask = CP_ALL_CATEGORIES; filter.mask = category_masks[go->layer] | editor_cat; @@ -138,7 +103,7 @@ void go_shape_apply(cpBody *body, cpShape *shape, struct gameobject *go) { ape->apply(ape->data); } -void go_shape_moi(cpBody *body, cpShape *shape, struct gameobject *go) { +void go_shape_moi(cpBody *body, cpShape *shape, gameobject *go) { float moment = cpBodyGetMoment(go->body); struct phys2d_shape *s = cpShapeGetUserData(shape); if (!s) { @@ -151,7 +116,7 @@ void go_shape_moi(cpBody *body, cpShape *shape, struct gameobject *go) { cpBodySetMoment(go->body, 1); } -void gameobject_apply(struct gameobject *go) { +void gameobject_apply(gameobject *go) { cpBodySetType(go->body, go->bodytype); cpBodyEachShape(go->body, go_shape_apply, go); @@ -169,7 +134,7 @@ void gameobject_apply(struct gameobject *go) { static void velocityFn(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt) { - struct gameobject *go = id2go((int)cpBodyGetUserData(body)); + gameobject *go = body2go(body); if (!go) { cpBodyUpdateVelocity(body,gravity,damping,dt); return; @@ -190,8 +155,9 @@ static void velocityFn(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt } } -int MakeGameobject() { - struct gameobject go = { +gameobject *MakeGameobject() { + gameobject *ngo = malloc(sizeof(*ngo)); + gameobject go = { .scale = (HMM_Vec3){1.f,1.f,1.f}, .bodytype = CP_BODY_TYPE_STATIC, .maxvelocity = INFINITY, @@ -206,6 +172,8 @@ int MakeGameobject() { .damping = NAN, .timescale = 1.0, .ref = JS_UNDEFINED, + .parent = NULL, + .children = NULL }; go.cbs.begin.obj = JS_UNDEFINED; @@ -214,16 +182,13 @@ int MakeGameobject() { go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f)); cpBodySetVelocityUpdateFunc(go.body, velocityFn); - int id; - if (!gameobjects) freelist_size(gameobjects,500); - freelist_grab(id, gameobjects); - cpBodySetUserData(go.body, (void*)id); - phys2d_setup_handlers(id); - gameobjects[id] = go; - return id; + *ngo = go; + cpBodySetUserData(go.body, ngo); + phys2d_setup_handlers(ngo); + return ngo; } -void gameobject_traverse(struct gameobject *go, HMM_Mat4 p) +void gameobject_traverse(gameobject *go, HMM_Mat4 p) { HMM_Mat4 local = transform3d2mat(go2t3(go)); go->world = HMM_MulM4(local, p); @@ -242,36 +207,30 @@ void rm_body_shapes(cpBody *body, cpShape *shape, void *data) { cpShapeFree(shape); } -int *go_toclean = NULL; +gameobject **go_toclean = NULL; /* Free this gameobject */ -void gameobject_clean(int id) { - struct gameobject *go = id2go(id); +void gameobject_clean(gameobject *go) { arrfree(go->shape_cbs); cpBodyEachShape(go->body, rm_body_shapes, NULL); cpSpaceRemoveBody(space, go->body); cpBodyFree(go->body); go->body = NULL; + + free(go); } /* Really more of a "mark for deletion" ... */ -void gameobject_delete(int id) { - gameobject *go = id2go(id); +void gameobject_free(gameobject *go) { + if (!go) return; + YughWarn("FREEING A GAMEOBJECT"); JS_FreeValue(js, go->ref); + dag_clip(go); if (cpSpaceIsLocked(space)) - arrpush(go_toclean, id); + arrpush(go_toclean, go); else - gameobject_clean(id); - - dag_clip(go); - freelist_kill(gameobjects,id); -} - -void gameobject_free(int id) -{ - if (id >= 0) - gameobject_delete(id); + gameobject_clean(go); } void gameobjects_cleanup() { @@ -281,12 +240,12 @@ void gameobjects_cleanup() { arrsetlen(go_toclean, 0); } -void gameobject_setangle(struct gameobject *go, float angle) { +void gameobject_setangle(gameobject *go, float angle) { cpBodySetAngle(go->body, angle); phys2d_reindex_body(go->body); } -void gameobject_setpos(struct gameobject *go, cpVect vec) { +void gameobject_setpos(gameobject *go, cpVect vec) { if (!go || !go->body) return; cpBodySetPosition(go->body, vec); phys2d_reindex_body(go->body); @@ -297,15 +256,9 @@ void body_draw_shapes_dbg(cpBody *body, cpShape *shape, void *data) { s->debugdraw(s->data); } -void gameobject_draw_debug(int go) { - struct gameobject *g = id2go(go); - if (!g || !g->body) return; +void gameobject_draw_debug(gameobject *go) { + if (!go || !go->body) return; - cpVect pos = cpBodyGetPosition(g->body); - cpBodyEachShape(g->body, body_draw_shapes_dbg, NULL); -} - -void gameobject_draw_debugs() { - for (int i = 0; i < arrlen(gameobjects); i++) - gameobject_draw_debug(i); + cpVect pos = cpBodyGetPosition(go->body); + cpBodyEachShape(go->body, body_draw_shapes_dbg, NULL); } diff --git a/source/engine/gameobject.h b/source/engine/gameobject.h index e446dc7..8c3d32e 100644 --- a/source/engine/gameobject.h +++ b/source/engine/gameobject.h @@ -1,11 +1,11 @@ #ifndef GAMEOBJECT_H #define GAMEOBJECT_H -#include "2dphysics.h" #include #include "quickjs/quickjs.h" #include "HandmadeMath.h" #include "transform.h" +#include "script.h" #define dag_rm(p,c) do{\ for (int i = arrlen(p->children)-1; i--; i >=0) {\ @@ -26,7 +26,7 @@ dag_rm(p->parent,p);\ }while(0) -typedef struct gameobject { +struct gameobject { cpBodyType bodytype; cpBody *body; /* NULL if this object is dead; has 2d position and rotation, relative to global 0 */ HMM_Vec3 scale; /* local */ @@ -51,53 +51,46 @@ typedef struct gameobject { float drawlayer; struct gameobject *parent; struct gameobject **children; -} gameobject; +}; -extern struct gameobject *gameobjects; +typedef struct gameobject gameobject; -int MakeGameobject(); -void gameobject_apply(struct gameobject *go); -void gameobject_delete(int id); -void gameobject_free(int id); +gameobject *MakeGameobject(); +void gameobject_apply(gameobject *go); +void gameobject_free(gameobject *go); void gameobjects_cleanup(); -void gameobject_traverse(struct gameobject *start, HMM_Mat4 p); +void gameobject_traverse(gameobject *start, HMM_Mat4 p); transform2d go2t(gameobject *go); transform3d go2t3(gameobject *go); -HMM_Vec2 go2world(struct gameobject *go, HMM_Vec2 pos); -HMM_Vec2 world2go(struct gameobject *go, HMM_Vec2 pos); +HMM_Vec2 go2world(gameobject *go, HMM_Vec2 pos); +HMM_Vec2 world2go(gameobject *go, HMM_Vec2 pos); -HMM_Mat3 t_go2world(struct gameobject *go); -HMM_Mat3 t_world2go(struct gameobject *go); -HMM_Mat4 t3d_go2world(struct gameobject *go); -HMM_Mat4 t3d_world2go(struct gameobject *go); +HMM_Mat3 t_go2world(gameobject *go); +HMM_Mat3 t_world2go(gameobject *go); +HMM_Mat4 t3d_go2world(gameobject *go); +HMM_Mat4 t3d_world2go(gameobject *go); -HMM_Vec2 go_pos(struct gameobject *go); -HMM_Vec2 go_worldpos(struct gameobject *go); -//float go_angle(struct gameobject *go); -float go_worldangle(struct gameobject *go); +HMM_Vec2 go_pos(gameobject *go); +HMM_Vec2 go_worldpos(gameobject *go); +//float go_angle(gameobject *go); +float go_worldangle(gameobject *go); -float go2angle(struct gameobject *go); +float go2angle(gameobject *go); -struct gameobject *id2go(int id); -int go2id(struct gameobject *go); -int body2id(cpBody *body); -cpBody *id2body(int id); -int shape2gameobject(cpShape *shape); -struct gameobject *shape2go(cpShape *shape); +gameobject *body2go(cpBody *body); +gameobject *shape2go(cpShape *shape); -void go_shape_apply(cpBody *body, cpShape *shape, struct gameobject *go); +void go_shape_apply(cpBody *body, cpShape *shape, gameobject *go); /* Tries a few methods to select a gameobject; if none is selected returns -1 */ -int pos2gameobject(HMM_Vec2 pos); +gameobject *pos2gameobject(HMM_Vec2 pos); -void gameobject_move(struct gameobject *go, HMM_Vec2 vec); -void gameobject_rotate(struct gameobject *go, float as); -void gameobject_setangle(struct gameobject *go, float angle); -void gameobject_setpos(struct gameobject *go, cpVect vec); - -void gameobject_draw_debugs(); -void gameobject_draw_debug(int go); +void gameobject_move(gameobject *go, HMM_Vec2 vec); +void gameobject_rotate(gameobject *go, float as); +void gameobject_setangle(gameobject *go, float angle); +void gameobject_setpos(gameobject *go, cpVect vec); +void gameobject_draw_debug(gameobject *go); #endif diff --git a/source/engine/jsffi.c b/source/engine/jsffi.c index 5d243f1..223f081 100644 --- a/source/engine/jsffi.c +++ b/source/engine/jsffi.c @@ -8,7 +8,6 @@ #include "font.h" #include "gameobject.h" #include "input.h" -#include "level.h" #include "log.h" #include "dsp.h" #include "music.h" @@ -51,11 +50,8 @@ static JSValue TYPE##2js(TYPE *n) { \ JS_SetOpaque(j,n);\ return j; }\ + QJSCLASS(dsp_node) - -// gameobject2js, js2gameobject deals with gameobject*, converted to ids -// go2js,js2go deals with gameobject* - QJSCLASS(gameobject) #define QJSCLASSPREP(TYPE) \ @@ -123,22 +119,13 @@ JSValue jscurtime() return jst; } -void js_setprop_num(JSValue obj, uint32_t i, JSValue v) -{ - JS_SetPropertyUint32(js, obj, i, v); -} +void js_setprop_num(JSValue obj, uint32_t i, JSValue v) { JS_SetPropertyUint32(js, obj, i, v); } -JSValue go2ref(int id) -{ - if (id == -1) return JS_UNDEFINED; - return JS_DupValue(js,id2go(id)->ref); -} - -JSValue gos2ref(int *go) +JSValue gos2ref(gameobject **go) { JSValue array = JS_NewArray(js); for (int i = 0; i < arrlen(go); i++) - js_setprop_num(array,i,go2ref(go[i])); + js_setprop_num(array,i,go[i]->ref); return array; } @@ -198,26 +185,11 @@ double js2number(JSValue v) { return g; } - -JSValue float2js(double g) { - return JS_NewFloat64(js, g); -} - -JSValue num2js(double g) { - return float2js(g); -} - -struct gameobject *js2go(JSValue v) { - return id2go(js2gameobject(v)); -} - -static int jsgo2id(JSValue v) { return go2id(js2go(v)); } - +JSValue float2js(double g) { return JS_NewFloat64(js, g);} +JSValue num2js(double g) { return float2js(g); } struct sprite *js2sprite(JSValue v) { return id2sprite(js2int(v)); } -void *js2ptr(JSValue v) { - return JS_GetOpaque(v,js_ptr_id); -} +void *js2ptr(JSValue v) { return JS_GetOpaque(v,js_ptr_id); } JSValue ptr2js(void *ptr) { JSValue obj = JS_NewObjectClass(js, js_ptr_id); @@ -225,9 +197,7 @@ JSValue ptr2js(void *ptr) { return obj; } -struct timer *js2timer(JSValue v) { - return id2timer(js2int(v)); -} +struct timer *js2timer(JSValue v) { return id2timer(js2int(v)); } double js_get_prop_number(JSValue v, const char *p) { double num; @@ -244,9 +214,7 @@ struct glrect js2glrect(JSValue v) { return rect; } -JSValue js_arridx(JSValue v, int idx) { - return js_getpropidx( v, idx); -} +JSValue js_arridx(JSValue v, int idx) { return js_getpropidx( v, idx); } int js_arrlen(JSValue v) { int len; @@ -541,6 +509,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) const void *d1 = NULL; const void *d2 = NULL; int *ids = NULL; + gameobject *go = NULL; JSValue ret = JS_UNDEFINED; switch (cmd) { @@ -555,9 +524,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 2: - YughWarn("Deleting gameobject %d", js2int(argv[1])); - gameobject_delete(js2int(argv[1])); - YughWarn("Deleted gameobject %d", js2int(argv[1])); + gameobject_free(js2int(argv[1])); break; case 3: @@ -699,9 +666,9 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 36: - js2go(argv[1])->scale.XY = js2vec2(argv[2]); - gameobject_apply(js2go(argv[1])); - cpSpaceReindexShapesForBody(space, js2go(argv[1])->body); + js2gameobject(argv[1])->scale.XY = js2vec2(argv[2]); + gameobject_apply(js2gameobject(argv[1])); + cpSpaceReindexShapesForBody(space, js2gameobject(argv[1])->body); break; case 37: @@ -722,25 +689,26 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 40: - js2go(argv[1])->filter.categories = js2bitmask(argv[2]); - gameobject_apply(js2go(argv[1])); + js2gameobject(argv[1])->filter.categories = js2bitmask(argv[2]); + gameobject_apply(js2gameobject(argv[1])); break; case 41: - js2go(argv[1])->filter.mask = js2bitmask(argv[2]); - gameobject_apply(js2go(argv[1])); + js2gameobject(argv[1])->filter.mask = js2bitmask(argv[2]); + gameobject_apply(js2gameobject(argv[1])); break; case 42: - ret = bitmask2js(js2go(argv[1])->filter.categories); + ret = bitmask2js(js2gameobject(argv[1])->filter.categories); break; case 43: - ret = bitmask2js(js2go(argv[1])->filter.mask); + ret = bitmask2js(js2gameobject(argv[1])->filter.mask); break; case 44: - ret = go2ref(pos2gameobject(js2vec2(argv[1]))); + go = pos2gameobject(js2vec2(argv[1])); + ret = go ? go->ref : JS_UNDEFINED; break; case 45: @@ -782,23 +750,23 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 54: - gameobject_apply(js2go(argv[1])); + gameobject_apply(js2gameobject(argv[1])); break; case 55: break; -// js2go(argv[1])->flipx = JS_ToBool(js, argv[2]) ? -1 : 1; +// js2gameobject(argv[1])->flipx = JS_ToBool(js, argv[2]) ? -1 : 1; case 56: -// js2go(argv[1])->flipy = JS_ToBool(js, argv[2]) ? -1 : 1; +// js2gameobject(argv[1])->flipy = JS_ToBool(js, argv[2]) ? -1 : 1; break; case 57: -// ret = JS_NewBool(js, js2go(argv[1])->flipx == -1 ? 1 : 0); +// ret = JS_NewBool(js, js2gameobject(argv[1])->flipx == -1 ? 1 : 0); break; case 58: -// ret = JS_NewBool(js, js2go(argv[1])->flipy == -1 ? 1 : 0); +// ret = JS_NewBool(js, js2gameobject(argv[1])->flipy == -1 ? 1 : 0); break; case 59: @@ -811,7 +779,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 61: - set_cam_body(id2body(js2int(argv[1]))); + set_cam_body(js2gameobject(argv[1])->body); break; case 62: @@ -847,11 +815,11 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 70: - ret = vec2js(world2go(js2go(argv[1]), js2vec2(argv[2]))); + ret = vec2js(world2go(js2gameobject(argv[1]), js2vec2(argv[2]))); break; case 71: - ret = vec2js(go2world(js2go(argv[1]), js2vec2(argv[2]))); + ret = vec2js(go2world(js2gameobject(argv[1]), js2vec2(argv[2]))); break; case 72: @@ -867,7 +835,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 75: - js2go(argv[1])->layer = js2int(argv[2]); + js2gameobject(argv[1])->layer = js2int(argv[2]); break; case 76: @@ -875,7 +843,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 77: - ret = int2js(js2go(argv[1])->layer); + ret = int2js(js2gameobject(argv[1])->layer); break; case 78: @@ -896,7 +864,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 82: - gameobject_draw_debug(js2go(argv[1])); + gameobject_draw_debug(js2gameobject(argv[1])); break; case 83: @@ -989,35 +957,35 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 103: - ret = vec2js(js2go(argv[1])->scale.XY); + ret = vec2js(js2gameobject(argv[1])->scale.XY); break; case 104: -// ret = bool2js(js2go(argv[1])->flipx == -1 ? 1 : 0); +// ret = bool2js(js2gameobject(argv[1])->flipx == -1 ? 1 : 0); break; case 105: -// ret = bool2js(js2go(argv[1])->flipy == -1 ? 1 : 0); +// ret = bool2js(js2gameobject(argv[1])->flipy == -1 ? 1 : 0); break; case 106: - js2go(argv[1])->e = js2number(argv[2]); + js2gameobject(argv[1])->e = js2number(argv[2]); break; case 107: - ret = num2js(js2go(argv[1])->e); + ret = num2js(js2gameobject(argv[1])->e); break; case 108: - js2go(argv[1])->f = js2number(argv[2]); + js2gameobject(argv[1])->f = js2number(argv[2]); break; case 109: - ret = num2js(js2go(argv[1])->f); + ret = num2js(js2gameobject(argv[1])->f); break; case 110: - ret = num2js(js2go(argv[1])->e); + ret = num2js(js2gameobject(argv[1])->e); break; case 111: @@ -1029,7 +997,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 113: - js2go(argv[1])->ref = argv[2];//JS_DupValue(js,argv[2]); + js2gameobject(argv[1])->ref = argv[2];//JS_DupValue(js,argv[2]); break; case 114: @@ -1188,38 +1156,38 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 151: - js2go(argv[1])->maxvelocity = js2number(argv[2]); + js2gameobject(argv[1])->maxvelocity = js2number(argv[2]); break; case 152: - ret = num2js(js2go(argv[1])->maxvelocity); + ret = num2js(js2gameobject(argv[1])->maxvelocity); break; case 153: - cpBodySetTorque(js2go(argv[1])->body, js2number(argv[2])); + cpBodySetTorque(js2gameobject(argv[1])->body, js2number(argv[2])); break; case 154: - js2go(argv[1])->maxangularvelocity = js2number(argv[2]); + js2gameobject(argv[1])->maxangularvelocity = js2number(argv[2]); break; case 155: - ret = num2js(js2go(argv[1])->maxangularvelocity); + ret = num2js(js2gameobject(argv[1])->maxangularvelocity); break; case 156: - js2go(argv[1])->damping = js2number(argv[2]); + js2gameobject(argv[1])->damping = js2number(argv[2]); break; case 157: - ret = num2js(js2go(argv[1])->damping); + ret = num2js(js2gameobject(argv[1])->damping); break; case 158: - js2go(argv[1])->gravity = js2bool(argv[2]); + js2gameobject(argv[1])->gravity = js2bool(argv[2]); break; case 159: - ret = bool2js(js2go(argv[1])->gravity); + ret = bool2js(js2gameobject(argv[1])->gravity); break; case 160: - ret = vec2js(mat_t_dir(t_world2go(js2go(argv[1])), js2vec2(argv[2]))); + ret = vec2js(mat_t_dir(t_world2go(js2gameobject(argv[1])), js2vec2(argv[2]))); break; case 161: - ret = vec2js(mat_t_dir(t_go2world(js2go(argv[1])), js2vec2(argv[2]))); + ret = vec2js(mat_t_dir(t_go2world(js2gameobject(argv[1])), js2vec2(argv[2]))); break; case 162: str = JS_ToCString(js, argv[1]); @@ -1242,22 +1210,22 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) ret = int2js(cp(str, str2)); break; case 167: - js2go(argv[1])->cgravity = js2vec2(argv[2]); + js2gameobject(argv[1])->cgravity = js2vec2(argv[2]); break; case 168: - js2go(argv[1])->timescale = js2number(argv[2]); + js2gameobject(argv[1])->timescale = js2number(argv[2]); break; case 169: - ret = num2js(js2go(argv[1])->timescale); + ret = num2js(js2gameobject(argv[1])->timescale); break; case 170: id2sprite(js2int(argv[1]))->emissive = js2color(argv[2]); break; case 171: - ret = num2js(js2go(argv[1])->drawlayer); + ret = num2js(js2gameobject(argv[1])->drawlayer); break; case 172: - js2go(argv[1])->drawlayer = js2number(argv[2]); + js2gameobject(argv[1])->drawlayer = js2number(argv[2]); break; case 173: str = js2str(argv[1]); @@ -1373,7 +1341,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) ret = dsp_node2js(dsp_fwd_delay(js2number(argv[1]), js2number(argv[2]))); break; case 208: - dag_set(js2go(argv[1]), js2go(argv[2])); + dag_set(js2gameobject(argv[1]), js2gameobject(argv[2])); break; case 209: ret = unix2time(js2number(argv[1])); @@ -1460,23 +1428,23 @@ JSValue duk_register(JSContext *js, JSValueConst this, int argc, JSValueConst *a return JS_UNDEFINED; } -void gameobject_add_shape_collider(int go, struct callee c, struct phys2d_shape *shape) { +void gameobject_add_shape_collider(gameobject *go, struct callee c, struct phys2d_shape *shape) { struct shape_cb shapecb; shapecb.shape = shape; shapecb.cbs.begin = c; - arrpush(id2go(go)->shape_cbs, shapecb); + arrpush(go->shape_cbs, shapecb); } JSValue duk_register_collide(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { int cmd = js2int(argv[0]); - int go = jsgo2id(argv[3]); + gameobject *go = js2gameobject(argv[3]); struct callee c; c.fn = argv[1]; c.obj = argv[2]; switch (cmd) { case 0: - id2go(go)->cbs.begin = c; + go->cbs.begin = c; break; case 1: @@ -1488,7 +1456,7 @@ JSValue duk_register_collide(JSContext *js, JSValueConst this, int argc, JSValue break; case 3: - id2go(go)->cbs.separate = c; + go->cbs.separate = c; break; } @@ -1533,7 +1501,6 @@ JSValue duk_sys_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *ar return JS_NewInt64(js, frame_fps()); case 9: /* Clear the level out */ - new_level(); break; case 10: @@ -1545,6 +1512,7 @@ JSValue duk_sys_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *ar } JSValue duk_make_gameobject(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { + YughWarn("MAKING GAMOBJECT"); return gameobject2js(MakeGameobject()); } @@ -1564,7 +1532,7 @@ JSValue duk_yughlog(JSContext *js, JSValueConst this, int argc, JSValueConst *ar JSValue duk_set_body(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { int cmd = js2int(argv[0]); - struct gameobject *go = js2go(argv[1]); + gameobject *go = js2gameobject(argv[1]); if (!go) return JS_UNDEFINED; @@ -1638,7 +1606,7 @@ JSValue duk_set_body(JSContext *js, JSValueConst this, int argc, JSValueConst *a JSValue duk_q_body(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { int q = js2int(argv[0]); - struct gameobject *go = js2go(argv[1]); + gameobject *go = js2gameobject(argv[1]); if (!go) return JS_UNDEFINED; @@ -1668,7 +1636,7 @@ JSValue duk_q_body(JSContext *js, JSValueConst this, int argc, JSValueConst *arg return JS_NewBool(js, phys2d_in_air(go->body)); case 8: - gameobject_delete(go2id(go)); + gameobject_free(go); break; } @@ -1695,7 +1663,7 @@ JSValue duk_make_anim2d(JSContext *js, JSValueConst this, int argc, JSValueConst } JSValue duk_make_box2d(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { - int go = jsgo2id(argv[0]); + gameobject *go = js2gameobject(argv[0]); HMM_Vec2 size = js2vec2(argv[1]); struct phys2d_box *box = Make2DBox(go); @@ -1736,7 +1704,7 @@ JSValue duk_cmd_box2d(JSContext *js, JSValueConst this, int argc, JSValueConst * } JSValue duk_make_circle2d(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { - int go = jsgo2id(argv[0]); + gameobject *go = js2gameobject(argv[0]); struct phys2d_circle *circle = Make2DCircle(go); @@ -1748,7 +1716,7 @@ JSValue duk_make_circle2d(JSContext *js, JSValueConst this, int argc, JSValueCon JSValue duk_make_model(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { - int go = jsgo2id(argv[0]); + gameobject *go = js2gameobject(argv[0]); struct drawmodel *dm = make_drawmodel(go); JSValue ret = JS_NewObject(js); js_setprop_str(ret, "id", ptr2js(dm)); @@ -1782,7 +1750,7 @@ JSValue duk_cmd_circle2d(JSContext *js, JSValueConst this, int argc, JSValueCons } JSValue duk_make_poly2d(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { - int go = jsgo2id(argv[0]); + gameobject *go = js2gameobject(argv[0]); struct phys2d_poly *poly = Make2DPoly(go); phys2d_poly_setverts(poly, NULL); JSValue polyval = JS_NewObject(js); @@ -1807,7 +1775,7 @@ JSValue duk_cmd_poly2d(JSContext *js, JSValueConst this, int argc, JSValueConst } JSValue duk_make_edge2d(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { - int go = jsgo2id(argv[0]); + gameobject *go = js2gameobject(argv[0]); struct phys2d_edge *edge = Make2DEdge(go); int n = js_arrlen(argv[1]); diff --git a/source/engine/level.c b/source/engine/level.c deleted file mode 100644 index 2c70409..0000000 --- a/source/engine/level.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "level.h" -#include "gameobject.h" -#include "resources.h" -#include -#include - -#include "stb_ds.h" - -void save_level(char name[MAXNAME]) { - FILE *lfile = res_open(name, "wb+"); - - if (!lfile) return; - - int objs = arrlen(gameobjects); - fwrite(&objs, sizeof(objs), 1, lfile); - - fclose(lfile); -} - -void load_level(char name[MAXNAME]) { - /* - FILE *lfile = fopen(name, "rb"); - - if (!lfile) return; - - new_level(); - - int objs; - fread(&objs, sizeof(objs), 1, lfile); - - arraddn(gameobjects, objs); - - for (int i = 0; i < objs; i++) { - struct gameobject *go = &gameobjects[i]; - fread(go, sizeof(struct gameobject), 1, lfile); - go->components = NULL; - gameobject_init(go, lfile); - } - - fclose(lfile); - */ -} - -void new_level() { - for (int i = 0; i < arrlen(gameobjects); i++) - gameobject_delete(i); - - arrfree(gameobjects); -} diff --git a/source/engine/level.h b/source/engine/level.h deleted file mode 100644 index b638fdd..0000000 --- a/source/engine/level.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef LEVEL_H -#define LEVEL_H - -#include "config.h" - -// This class holds all of the entities and options for a level. Really it's nothing more than a container and access point for all the entities currently loaded into the game. - -struct level { - char name[MAXNAME]; -}; - -void save_level(char name[MAXNAME]); -void load_level(char name[MAXNAME]); -void new_level(); - -#endif diff --git a/source/engine/render.c b/source/engine/render.c index 88c58dc..aaa00cb 100644 --- a/source/engine/render.c +++ b/source/engine/render.c @@ -518,10 +518,9 @@ void full_2d_pass(struct window *window) call_draw(); //// DEBUG - if (debugDrawPhysics) { - gameobject_draw_debugs(); + if (debugDrawPhysics) call_debugs(); - } + debug_flush(&projection); text_flush(&projection); diff --git a/source/engine/script.h b/source/engine/script.h index b3a51a2..9c59104 100644 --- a/source/engine/script.h +++ b/source/engine/script.h @@ -12,6 +12,12 @@ struct callee { JSValue obj; }; +struct phys_cbs { + struct callee begin; + struct callee separate; +}; + + extern struct callee stacktrace_callee; extern JSValue num_cache[100]; diff --git a/source/engine/spline.c b/source/engine/spline.c new file mode 100644 index 0000000..0519de7 --- /dev/null +++ b/source/engine/spline.c @@ -0,0 +1,334 @@ +#include "spline.h" +#include "stb_ds.h" +#include "log.h" +#include "transform.h" + +static const HMM_Mat4 cubic_hermite_m = { + 2, -2, 1, 1, + -3, 3, -2, -1, + 0, 0, 1, 0, + 1, 0, 0, 0 +}; + +static const HMM_Mat4 cubic_hermite_dm = { + 0, 0, 0, 0, + 6, -6, 3, 3, + -6, 6, -4, -2, + 0, 0, 1, 0 +}; + +static const HMM_Mat4 cubic_hermite_ddm = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 12, -12, 6, 6, + -6, 6, -4, -2 +}; + +static const HMM_Mat4 cubic_hermite_dddm = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 12, -12, 6, 6 +}; + +static const HMM_Mat4 b_spline_m = { + -1/6, 3/6, -3/6, 1, + 3/6, -6/6, 3/6, 0, + -3/6, 0, 3/6, 0, + 1/6, 4/6, 1/6, 0 +}; + +static const HMM_Mat4 b_spline_dm = { + 0, 0, 0, 0, + -3/6, 9/6, -9/6, 3, + 6/6, -12/6, 6/6, 0, + -3/6, 0, 3/6, 0 +}; + +static const HMM_Mat4 b_spline_ddm = { + 0, 0, 0, 0, + 0, 0, 0, 0, + -6/6, 18/6, -18/6, 6, + 6/6, -12/6, 6/6, 0 +}; + +static const HMM_Mat4 b_spline_dddm = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + -6/6, 18/6, -18/6, 6 +}; + +static const HMM_Mat4 bezier_m = { + -1, 3, -3, 1, + 3, -6, 3, 0, + -3, 3, 0, 0, + 1, 0, 0, 0 +}; + +static const HMM_Mat4 bezier_dm = { + 0, 0, 0, 0, + -3, 9, -9, 3, + 6, -12, 6, 0, + -3, 3, 0, 0, +}; + +static const HMM_Mat4 bezier_ddm = { + 0, 0, 0, 0, + 0, 0, 0, 0, + -6, 18, -18, 6, + 6, -12, 6, 0 +}; + +static const HMM_Mat4 bezier_dddm = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + -6, 18, -18, 6 +}; + +#define CAT_S 0.5 + +/* Position */ +static const HMM_Mat4 catmull_rom_m = { + -CAT_S, 2-CAT_S, CAT_S-2, CAT_S, + 2*CAT_S, CAT_S-3, 3-2*CAT_S, -CAT_S, + -CAT_S, 0, CAT_S, 0, + 0, 1, 0, 0 +}; + +/* Tangent */ +static const HMM_Mat4 catmull_rom_dm = { + 0, 0, 0, 0, + -3*CAT_S, 9*CAT_S, -9*CAT_S, 3*CAT_S, + 4*CAT_S, -10*CAT_S, 8*CAT_S, -2*CAT_S, + -CAT_S, 0, CAT_S, 0, +}; + +/* Curvature */ +static const HMM_Mat4 catmull_rom_ddm = { + 0, 0, 0, 0, + 0, 0, 0, 0, + -9*CAT_S, 18*CAT_S, -18*CAT_S, 6*CAT_S, + 4*CAT_S, -10*CAT_S, 8*CAT_S, -2*CAT_S +}; + +/* Wiggle */ +static const HMM_Mat4 catmull_rom_dddm = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + -9*CAT_S, 18*CAT_S, -18*CAT_S, 6*CAT_S +}; + +HMM_Vec4 spline_CT(HMM_Mat4 *C, float t) +{ + float t2 = t*t; + float t3 = t2*t; + HMM_Vec4 T = {t3, t2, t, 1}; + return HMM_MulM4V4(*C, T); +} + +HMM_Mat4 make_G(HMM_Vec2 a, HMM_Vec2 b, HMM_Vec2 c, HMM_Vec2 d) +{ + HMM_Mat4 G; + G.Columns[0].xy = a; + G.Columns[1].xy = b; + G.Columns[2].xy = c; + G.Columns[3].xy = d; + return G; +} + +HMM_Mat4 make_C(HMM_Vec2 p0, HMM_Vec2 p1, HMM_Vec2 p2, HMM_Vec2 p3, HMM_Mat4 *B) +{ + HMM_Mat4 G = make_G(p0, p1, p2, p3); + return HMM_MulM4(G, *B); +} + +HMM_Vec2 cubic_spline_d(HMM_Vec2 p0, HMM_Vec2 p1, HMM_Vec2 p2, HMM_Vec2 p3, HMM_Mat4 *m, float d) +{ + HMM_Mat4 G = make_G(p0,p1,p2,p3); + HMM_Mat4 C = HMM_MulM4(G, *m); + return spline_CT(&C, d).xy; +} + +HMM_Vec2 *spline_v2(HMM_Vec2 *a, HMM_Vec2 *b, HMM_Vec2 *c, HMM_Vec2 *d, HMM_Mat4 *m, int segs) +{ + HMM_Vec2 *ret = NULL; + if (segs == 2) { + arrput(ret, *b); + arrput(ret, *c); + return ret; + } + if (segs < 2) return NULL; + + HMM_Mat4 G = make_G(*a, *b, *c, *d); + HMM_Mat4 C = HMM_MulM4(G, *m); + float s = (float)1/segs; + + for (float t = 0; t < 1; t += s) + arrput(ret, spline_CT(&C, t).xy); + + return ret; +} + +HMM_Vec2 *spline2d_min_seg(float u0, float u1, float min_seg, HMM_Mat4 *C, HMM_Vec2 *ret) +{ + HMM_Vec2 a = spline_CT(C, u0).xy; + HMM_Vec2 b = spline_CT(C, u1).xy; + if (HMM_DistV2(a,b) > min_seg) { + float umid = (u0+u1)/2; + spline2d_min_seg(u0, umid, min_seg, C, ret); + spline2d_min_seg(umid, u1, min_seg, C, ret); + } + else + arrput(ret, b); +} + +HMM_Vec2 *catmull_rom_min_seg(HMM_Vec2 *a, HMM_Vec2 *b, HMM_Vec2 *c, HMM_Vec2 *d, float min_seg) +{ + HMM_Vec2 p0 = HMM_MulV2F(HMM_SubV2(*c, *a), CAT_S); + HMM_Vec2 p3 = HMM_MulV2F(HMM_SubV2(*d, *b), CAT_S); + + HMM_Mat4 G = make_G(p0, *b, *c, p3); + HMM_Mat4 C = HMM_MulM4(G, catmull_rom_m); + HMM_Vec2 *ret = NULL; + arrsetcap(ret, 100); + arrput(ret, *b); + spline2d_min_seg(0, 1, min_seg, &C, ret); + return ret; +} + +void *stbarrdup(void *mem, size_t size, int len) { + void *out = NULL; + arrsetlen(out, len); + memcpy(out,mem,size*len); + return out; +} + +#define arrconcat(a,b) do{for (int i = 0; i < arrlen(b); i++) arrput(a,b[i]);}while(0) +#define arrdup(a) (stbarrdup(a, sizeof(*a), arrlen(a))) + +static HMM_Vec2 *V2RET = NULL; +static HMM_Vec3 *V3RET = NULL; +static HMM_Vec4 *V4RET = NULL; + +#define SPLINE_MIN(DIM) \ +HMM_Vec##DIM *spline2d_min_angle_##DIM(float u0, float u1, float max_angle, HMM_Mat4 *C) \ +{ \ + float umid = (u0 + u1)/2;\ + HMM_Vec##DIM a = spline_CT(C, u0)._##DIM;\ + HMM_Vec##DIM b = spline_CT(C, u1)._##DIM;\ + HMM_Vec##DIM m = spline_CT(C, umid)._##DIM;\ + if (HMM_AngleV##DIM(m,b) > max_angle) {\ + spline2d_min_angle_##DIM(u0, umid, max_angle, C);\ + spline2d_min_angle_##DIM(umid, u1, max_angle, C);\ + }\ + else\ + arrput(V##DIM##RET,b);\ +}\ + +SPLINE_MIN(2) +SPLINE_MIN(3) + +/* Computes non even points to give the best looking curve */ +HMM_Vec2 *catmull_rom_min_angle(HMM_Vec2 *a, HMM_Vec2 *b, HMM_Vec2 *c, HMM_Vec2 *d, float min_angle) +{ + HMM_Mat4 G = make_G(*a, *b, *c, *d); + HMM_Mat4 C = HMM_MulM4(G, catmull_rom_m); + return spline2d_min_angle_2(0,1,min_angle*M_PI/180.0,&C); +} + +#define CR_MA(DIM) \ +HMM_Vec##DIM *catmull_rom_ma_v##DIM(HMM_Vec##DIM *cp, float ma) \ +{ \ + if (arrlen(cp) < 4) return NULL; \ +\ + if (V##DIM##RET) arrfree(V##DIM##RET);\ + arrsetcap(V##DIM##RET,100);\ + int segments = arrlen(cp)-3;\ + arrput(V##DIM##RET, cp[1]); \ + for (int i = 1; i < arrlen(cp)-2; i++) { \ + HMM_Vec##DIM p0 = HMM_MulV##DIM##F(HMM_SubV##DIM(cp[i+1], cp[i-1]), CAT_S);\ + HMM_Vec##DIM p3 = HMM_MulV##DIM##F(HMM_SubV##DIM(cp[i+2], cp[i]), CAT_S);\ + catmull_rom_min_angle(&p0, &cp[i], &cp[i+1], &p3, ma);\ + }\ + \ + return arrdup(V##DIM##RET);\ +}\ + +CR_MA(2) +CR_MA(3) +CR_MA(4) + +HMM_Vec2 catmull_rom_query(HMM_Vec2 *cp, float d, HMM_Mat4 *G) +{ + if (arrlen(cp) < 4 || d < 0 || d > 1) return HMM_V2(0,0); + + int segs = arrlen(cp)-3; + float d_per_seg = (float)1/segs; + float maxi = d_per_seg; + int p1 = 2; + while (maxi < d) { + maxi += d_per_seg; + p1++; + } + + HMM_Vec2 p0 = HMM_MulV2F(HMM_SubV2(cp[p1+1], cp[p1-1]), CAT_S); + HMM_Vec2 p3 = HMM_MulV2F(HMM_SubV2(cp[p1+2], cp[p1]), CAT_S); + + return cubic_spline_d(p0, cp[p1], cp[p1+1], p3, G, d); +} + +float catmull_rom_seglen(float t0, float t1, float max_angle, HMM_Mat4 *Cd, HMM_Mat4 *C) +{ + float total = 0; + float step = 0.1; + for (float i = t0; i < t1; i += step) + total += HMM_LenV2(spline_CT(Cd, i).xy) * step; + + return total; + + /* Estimation via max angle */ +/* float total = 0.0; + float tmid = (t0+t1)/2; + HMM_Vec2 a = spline_CT(C, t0).xy; + HMM_Vec2 b = spline_CT(C, t1).xy; + HMM_Vec2 m = spline_CT(C, tmid).xy; + + if (HMM_AngleV2(m,b) > max_angle) { + total += catmull_rom_seglen(t0, tmid, max_angle, Cd, C); + total += catmull_rom_seglen(tmid, t1, max_angle, Cd, C); + } else + return HMM_LenV2(spline_CT(Cd, t0).xy)*(t1-t0); + + return total; +*/ +} + +float catmull_rom_len(HMM_Vec2 *cp) +{ + float len = 0.0; + int segs = arrlen(cp)-3; + float d_per_seg = (float)1/segs; + float maxi = d_per_seg; + for (int i = 1; i < arrlen(cp)-2; i++) { + HMM_Vec2 p0 = HMM_MulV2F(HMM_SubV2(cp[i+1], cp[i-1]), CAT_S); + HMM_Vec2 p3 = HMM_MulV2F(HMM_SubV2(cp[i+2], cp[i]), CAT_S); + HMM_Mat4 C = make_C(p0, cp[i], cp[i+1], p3, &catmull_rom_m); + HMM_Mat4 Cd = make_C(p0, cp[i], cp[i+1], p3, &catmull_rom_dm); + len += catmull_rom_seglen(0, 1, 0.1, &Cd, &C); + } + return len; +} + +/* d is from 0 to 1 for the entire spline */ +HMM_Vec2 catmull_rom_pos(HMM_Vec2 *cp, float d) { return catmull_rom_query(cp,d,&catmull_rom_m); } +HMM_Vec2 catmull_rom_tan(HMM_Vec2 *cp, float d) { return catmull_rom_query(cp,d,&catmull_rom_dm); } +HMM_Vec2 catmull_rom_curv(HMM_Vec2 *cp, float d) { return catmull_rom_query(cp,d,&catmull_rom_ddm); } +HMM_Vec2 catmull_rom_wig(HMM_Vec2 *cp, float d) { return catmull_rom_query(cp,d,&catmull_rom_dddm); } + +HMM_Vec2 catmull_rom_closest(HMM_Vec2 *cp, HMM_Vec2 p) +{ + +} diff --git a/source/engine/spline.h b/source/engine/spline.h new file mode 100644 index 0000000..5259979 --- /dev/null +++ b/source/engine/spline.h @@ -0,0 +1,22 @@ +#ifndef SPLINE_H +#define SPLINE_H + +#include "HandmadeMath.h" + +HMM_Vec2 *catmull_rom_ma_v2(HMM_Vec2 *cp, float ma); +HMM_Vec3 *catmull_rom_ma_v3(HMM_Vec3 *cp, float ma); +HMM_Vec4 *catmull_rom_ma_v4(HMM_Vec4 *cp, float ma); + +HMM_Vec2 catmull_rom_query(HMM_Vec2 *cp, float d, HMM_Mat4 *G); + +HMM_Vec2 catmull_rom_pos(HMM_Vec2 *cp, float d); +HMM_Vec2 catmull_rom_tan(HMM_Vec2 *cp, float d); +HMM_Vec2 catmull_rom_curv(HMM_Vec2 *cp, float d); +HMM_Vec2 catmull_rom_wig(HMM_Vec2 *cp, float d); + +float catmull_rom_len(HMM_Vec2 *cp); + +/* Returns closest point on a curve given a point p */ +HMM_Vec2 catmull_rom_closest(HMM_Vec2 *cp, HMM_Vec2 p); + +#endif diff --git a/source/engine/sprite.c b/source/engine/sprite.c index dbe31ac..a3844e5 100644 --- a/source/engine/sprite.c +++ b/source/engine/sprite.c @@ -108,8 +108,8 @@ void sprite_io(struct sprite *sprite, FILE *f, int read) { int sprite_sort(int *a, int *b) { - struct gameobject *goa = id2go(sprites[*a].go); - struct gameobject *gob = id2go(sprites[*b].go); + struct gameobject *goa = sprites[*a].go; + struct gameobject *gob = sprites[*b].go; if (goa->drawlayer == gob->drawlayer) return 0; if (goa->drawlayer > gob->drawlayer) return 1; return -1; @@ -240,7 +240,7 @@ void tex_draw(struct Texture *tex, HMM_Mat3 m, struct glrect r, struct rgba colo } void sprite_draw(struct sprite *sprite) { - struct gameobject *go = id2go(sprite->go); + gameobject *go = sprite->go; if (sprite->tex) { HMM_Mat3 m = t_go2world(go); diff --git a/source/engine/sprite.h b/source/engine/sprite.h index c595f2c..aeb894b 100644 --- a/source/engine/sprite.h +++ b/source/engine/sprite.h @@ -7,15 +7,13 @@ #include "HandmadeMath.h" #include "render.h" #include "transform.h" - -struct datastream; -struct gameobject; +#include "gameobject.h" struct sprite { transform2d t; struct rgba color; struct rgba emissive; - int go; /* id of gameobject */ + gameobject *go; /* id of gameobject */ struct Texture *tex; struct glrect frame; int enabled; diff --git a/source/engine/yugine.c b/source/engine/yugine.c index 828d881..3fcf9a5 100644 --- a/source/engine/yugine.c +++ b/source/engine/yugine.c @@ -287,29 +287,12 @@ void c_event(const sapp_event *e) int sim_playing() { return sim_play == SIM_PLAY; } int sim_paused() { return sim_play == SIM_PAUSE; } - -void sim_start() { - sim_play = SIM_PLAY; -} - -void sim_pause() { - sim_play = SIM_PAUSE; -} - +void sim_start() { sim_play = SIM_PLAY; } +void sim_pause() { sim_play = SIM_PAUSE; } int phys_stepping() { return sim_play == SIM_STEP; } - -void sim_step() { - sim_play = SIM_STEP; -} - -void set_timescale(float val) { - timescale = val; -} - -double get_timescale() -{ - return timescale; -} +void sim_step() { sim_play = SIM_STEP; } +void set_timescale(float val) { timescale = val; } +double get_timescale() { return timescale; } static sapp_desc start_desc = { .width = 720, @@ -330,10 +313,7 @@ static sapp_desc start_desc = { .logger.func = sg_logging, }; -void app_name(char *name) -{ - start_desc.window_title = strdup(name); -} +void app_name(char *name) { start_desc.window_title = strdup(name); } int main(int argc, char **argv) { #ifndef NDEBUG