spline
This commit is contained in:
parent
5ad3219379
commit
9fb36f5df3
|
@ -141,8 +141,7 @@ var gameobject = {
|
||||||
this.set_worldpos(this.level.this2world(x));
|
this.set_worldpos(this.level.this2world(x));
|
||||||
},
|
},
|
||||||
|
|
||||||
get pos() { return cmd
|
get pos() {
|
||||||
|
|
||||||
if (!this.level) return this.worldpos();
|
if (!this.level) return this.worldpos();
|
||||||
return this.level.world2this(this.worldpos());
|
return this.level.world2this(this.worldpos());
|
||||||
},
|
},
|
||||||
|
@ -238,7 +237,8 @@ var gameobject = {
|
||||||
this.level?.remove_obj(this);
|
this.level?.remove_obj(this);
|
||||||
|
|
||||||
this.level = parent;
|
this.level = parent;
|
||||||
cmd(208,parent,this);
|
|
||||||
|
cmd(208,parent.body,this.body);
|
||||||
|
|
||||||
function unique_name(list, obj) {
|
function unique_name(list, obj) {
|
||||||
var str = obj.toString().replaceAll('.', '_');
|
var str = obj.toString().replaceAll('.', '_');
|
||||||
|
@ -310,13 +310,9 @@ var gameobject = {
|
||||||
return bb.t-bb.b;
|
return bb.t-bb.b;
|
||||||
},
|
},
|
||||||
|
|
||||||
move(vec) {
|
move(vec) { this.pos = this.pos.add(vec); },
|
||||||
this.pos = this.pos.add(vec);
|
|
||||||
},
|
|
||||||
|
|
||||||
rotate(amt) {
|
rotate(amt) { this.angle += amt; },
|
||||||
this.angle += amt;
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Make a unique object the same as its prototype */
|
/* Make a unique object the same as its prototype */
|
||||||
revert() {
|
revert() {
|
||||||
|
|
|
@ -33,9 +33,7 @@ static const float sensor_seg = 10;
|
||||||
|
|
||||||
unsigned int category_masks[32];
|
unsigned int category_masks[32];
|
||||||
|
|
||||||
void set_cat_mask(int cat, unsigned int mask) {
|
void set_cat_mask(int cat, unsigned int mask) { category_masks[cat] = mask; }
|
||||||
category_masks[cat] = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpTransform m3_to_cpt(HMM_Mat3 m)
|
cpTransform m3_to_cpt(HMM_Mat3 m)
|
||||||
{
|
{
|
||||||
|
@ -66,7 +64,7 @@ int sort_ids(int *a, int *b)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int *clean_ids(int *ids)
|
gameobject *clean_ids(int *ids)
|
||||||
{
|
{
|
||||||
qsort(ids, sizeof(*ids), arrlen(ids), sort_ids);
|
qsort(ids, sizeof(*ids), arrlen(ids), sort_ids);
|
||||||
|
|
||||||
|
@ -80,18 +78,16 @@ int *clean_ids(int *ids)
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
void querylist(cpShape *shape, cpContactPointSet *points, int *ids) {
|
void querylist(cpShape *shape, cpContactPointSet *points, int *ids) { arrput(ids,shape2go(shape)); }
|
||||||
arrput(ids,shape2gameobject(shape));
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct querybox {
|
typedef struct querybox {
|
||||||
cpBB bb;
|
cpBB bb;
|
||||||
int *ids;
|
gameobject **ids;
|
||||||
} querybox;
|
} querybox;
|
||||||
|
|
||||||
void querylistbodies(cpBody *body, querybox *qb) {
|
void querylistbodies(cpBody *body, querybox *qb) {
|
||||||
if (cpBBContainsVect(qb->bb, cpBodyGetPosition(body)))
|
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 */
|
/* 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 */
|
/* 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);
|
cpShape *box = cpBoxShapeNew(NULL, wh.x, wh.y, 0.f);
|
||||||
cpTransform T = {0};
|
cpTransform T = {0};
|
||||||
T.a = 1;
|
T.a = 1;
|
||||||
|
@ -134,8 +130,8 @@ int *phys2d_query_box(HMM_Vec2 pos, HMM_Vec2 wh) {
|
||||||
return clean_ids(ids);
|
return clean_ids(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
int *phys2d_query_shape(struct phys2d_shape *shape) {
|
gameobject *phys2d_query_shape(struct phys2d_shape *shape) {
|
||||||
int *ids = NULL;
|
gameobject **ids = NULL;
|
||||||
cpSpaceShapeQuery(space, shape->shape, querylist, ids);
|
cpSpaceShapeQuery(space, shape->shape, querylist, ids);
|
||||||
return clean_ids(ids);
|
return clean_ids(ids);
|
||||||
}
|
}
|
||||||
|
@ -184,10 +180,10 @@ void phys2d_update(float deltaT) {
|
||||||
flush_collide_cbs();
|
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->go = go;
|
||||||
shape->data = data;
|
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);
|
cpShapeSetCollisionType(shape->shape, go);
|
||||||
cpShapeSetUserData(shape->shape, shape);
|
cpShapeSetUserData(shape->shape, shape);
|
||||||
}
|
}
|
||||||
|
@ -199,13 +195,13 @@ void phys2d_shape_del(struct phys2d_shape *shape) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************** CIRCLE2D *****************/
|
/***************** CIRCLE2D *****************/
|
||||||
struct phys2d_circle *Make2DCircle(int go) {
|
struct phys2d_circle *Make2DCircle(gameobject *go) {
|
||||||
struct phys2d_circle *new = malloc(sizeof(struct phys2d_circle));
|
struct phys2d_circle *new = malloc(sizeof(struct phys2d_circle));
|
||||||
|
|
||||||
new->radius = 10.f;
|
new->radius = 10.f;
|
||||||
new->offset = v2zero;
|
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.debugdraw = phys2d_dbgdrawcircle;
|
||||||
new->shape.moi = phys2d_circle_moi;
|
new->shape.moi = phys2d_circle_moi;
|
||||||
new->shape.apply = phys2d_applycircle;
|
new->shape.apply = phys2d_applycircle;
|
||||||
|
@ -240,7 +236,7 @@ void phys2d_dbgdrawcircle(struct phys2d_circle *circle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void phys2d_applycircle(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));
|
float radius = circle->radius * HMM_MAX(HMM_ABS(go->scale.X), HMM_ABS(go->scale.Y));
|
||||||
cpCircleShapeSetRadius(circle->shape.shape, radius);
|
cpCircleShapeSetRadius(circle->shape.shape, radius);
|
||||||
|
@ -250,7 +246,7 @@ void phys2d_applycircle(struct phys2d_circle *circle) {
|
||||||
|
|
||||||
/************* BOX2D ************/
|
/************* BOX2D ************/
|
||||||
|
|
||||||
struct phys2d_box *Make2DBox(int go) {
|
struct phys2d_box *Make2DBox(gameobject *go) {
|
||||||
struct phys2d_box *new = malloc(sizeof(struct phys2d_box));
|
struct phys2d_box *new = malloc(sizeof(struct phys2d_box));
|
||||||
new->t = (transform2d){
|
new->t = (transform2d){
|
||||||
.pos = {0,0},
|
.pos = {0,0},
|
||||||
|
@ -277,7 +273,7 @@ void phys2d_boxdel(struct phys2d_box *box) {
|
||||||
|
|
||||||
void phys2d_applybox(struct phys2d_box *box) {
|
void phys2d_applybox(struct phys2d_box *box) {
|
||||||
phys2d_boxdel(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));
|
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}};
|
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));
|
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 ************/
|
/************** POLYGON ************/
|
||||||
|
|
||||||
struct phys2d_poly *Make2DPoly(int go) {
|
struct phys2d_poly *Make2DPoly(gameobject *go) {
|
||||||
struct phys2d_poly *new = malloc(sizeof(struct phys2d_poly));
|
struct phys2d_poly *new = malloc(sizeof(struct phys2d_poly));
|
||||||
|
|
||||||
new->points = NULL;
|
new->points = NULL;
|
||||||
arrsetlen(new->points, 0);
|
arrsetlen(new->points, 0);
|
||||||
new->radius = 0.f;
|
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.debugdraw = phys2d_dbgdrawpoly;
|
||||||
new->shape.moi = phys2d_poly_moi;
|
new->shape.moi = phys2d_poly_moi;
|
||||||
new->shape.apply = phys2d_applypoly;
|
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) {
|
void phys2d_applypoly(struct phys2d_poly *poly) {
|
||||||
if (arrlen(poly->points) <= 0) return;
|
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));
|
cpTransform T = m3_to_cpt(transform2d2mat(poly->t));
|
||||||
cpPolyShapeSetVerts(poly->shape.shape, arrlen(poly->points), poly->points, T);
|
cpPolyShapeSetVerts(poly->shape.shape, arrlen(poly->points), poly->points, T);
|
||||||
cpPolyShapeSetRadius(poly->shape.shape, poly->radius);
|
cpPolyShapeSetRadius(poly->shape.shape, poly->radius);
|
||||||
|
@ -379,7 +375,7 @@ void phys2d_dbgdrawpoly(struct phys2d_poly *poly) {
|
||||||
}
|
}
|
||||||
/****************** EDGE 2D**************/
|
/****************** EDGE 2D**************/
|
||||||
|
|
||||||
struct phys2d_edge *Make2DEdge(int go) {
|
struct phys2d_edge *Make2DEdge(gameobject *go) {
|
||||||
struct phys2d_edge *new = malloc(sizeof(struct phys2d_edge));
|
struct phys2d_edge *new = malloc(sizeof(struct phys2d_edge));
|
||||||
new->points = NULL;
|
new->points = NULL;
|
||||||
arrsetlen(new->points, 0);
|
arrsetlen(new->points, 0);
|
||||||
|
@ -414,7 +410,7 @@ void phys2d_edgedel(struct phys2d_edge *edge) {
|
||||||
void phys2d_edgeaddvert(struct phys2d_edge *edge) {
|
void phys2d_edgeaddvert(struct phys2d_edge *edge) {
|
||||||
arrput(edge->points, v2zero);
|
arrput(edge->points, v2zero);
|
||||||
if (arrlen(edge->points) > 1)
|
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);
|
phys2d_applyedge(edge);
|
||||||
}
|
}
|
||||||
|
@ -466,7 +462,7 @@ void phys2d_edge_addverts(struct phys2d_edge *edge, cpVect *verts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void phys2d_applyedge(struct phys2d_edge *edge) {
|
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++) {
|
for (int i = 0; i < arrlen(edge->shapes); i++) {
|
||||||
/* Points must be scaled with gameobject, */
|
/* Points must be scaled with gameobject, */
|
||||||
|
@ -480,7 +476,7 @@ void phys2d_applyedge(struct phys2d_edge *edge) {
|
||||||
cpShapeSetUserData(edge->shapes[i], &edge->shape);
|
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) {
|
void phys2d_dbgdrawedge(struct phys2d_edge *edge) {
|
||||||
|
@ -495,7 +491,7 @@ void phys2d_dbgdrawedge(struct phys2d_edge *edge) {
|
||||||
if (arrlen(edge->shapes) < 1) return;
|
if (arrlen(edge->shapes) < 1) return;
|
||||||
|
|
||||||
HMM_Vec2 drawpoints[arrlen(edge->points)];
|
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);
|
HMM_Mat3 g2w = t_go2world(go);
|
||||||
for (int i = 0; i < arrlen(edge->points); i++)
|
for (int i = 0; i < arrlen(edge->points); i++)
|
||||||
|
@ -563,7 +559,7 @@ void flush_collide_cbs() {
|
||||||
arrsetlen(begins,0);
|
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 *shape1;
|
||||||
cpShape *shape2;
|
cpShape *shape2;
|
||||||
cpArbiterGetShapes(arb, &shape1, &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, "pos", vec2js(srfv));
|
||||||
// JS_SetPropertyStr(js,obj,"depth", num2js(cpArbiterGetDepth(arb,0)));
|
// JS_SetPropertyStr(js,obj,"depth", num2js(cpArbiterGetDepth(arb,0)));
|
||||||
JS_SetPropertyStr(js, obj, "id", JS_NewInt32(js,hit));
|
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;
|
struct postphys_cb cb;
|
||||||
cb.c = c;
|
cb.c = c;
|
||||||
|
@ -594,11 +590,8 @@ static cpBool handle_collision(cpArbiter *arb, int type) {
|
||||||
cpBody *body1;
|
cpBody *body1;
|
||||||
cpBody *body2;
|
cpBody *body2;
|
||||||
cpArbiterGetBodies(arb, &body1, &body2);
|
cpArbiterGetBodies(arb, &body1, &body2);
|
||||||
int g1 = (int)cpBodyGetUserData(body1);
|
gameobject *go = cpBodyGetUserData(body1);
|
||||||
int g2 = (int)cpBodyGetUserData(body2);
|
gameobject *go2 = cpBodyGetUserData(body2);
|
||||||
struct gameobject *go = id2go(g1);
|
|
||||||
struct gameobject *go2 = id2go(g2);
|
|
||||||
|
|
||||||
cpShape *shape1;
|
cpShape *shape1;
|
||||||
cpShape *shape2;
|
cpShape *shape2;
|
||||||
cpArbiterGetShapes(arb, &shape1, &shape2);
|
cpArbiterGetShapes(arb, &shape1, &shape2);
|
||||||
|
@ -612,16 +605,16 @@ static cpBool handle_collision(cpArbiter *arb, int type) {
|
||||||
case CTYPE_BEGIN:
|
case CTYPE_BEGIN:
|
||||||
for (int i = 0; i < arrlen(go->shape_cbs); i++)
|
for (int i = 0; i < arrlen(go->shape_cbs); i++)
|
||||||
if (go->shape_cbs[i].shape == pshape1)
|
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))
|
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;
|
break;
|
||||||
|
|
||||||
case CTYPE_SEP:
|
case CTYPE_SEP:
|
||||||
if (JS_IsObject(go->cbs.separate.obj))
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -637,16 +630,16 @@ static cpBool script_phys_cb_separate(cpArbiter *arb, cpSpace *space, void *data
|
||||||
return handle_collision(arb, CTYPE_SEP);
|
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);
|
cpCollisionHandler *handler = cpSpaceAddWildcardHandler(space, go);
|
||||||
handler->userData = NULL;
|
handler->userData = NULL;
|
||||||
handler->beginFunc = NULL;
|
handler->beginFunc = NULL;
|
||||||
handler->separateFunc = NULL;
|
handler->separateFunc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void phys2d_setup_handlers(int go) {
|
void phys2d_setup_handlers(gameobject *go) {
|
||||||
cpCollisionHandler *handler = cpSpaceAddWildcardHandler(space, go);
|
cpCollisionHandler *handler = cpSpaceAddWildcardHandler(space, go);
|
||||||
handler->userData = (void *)go;
|
handler->userData = go;
|
||||||
handler->beginFunc = script_phys_cb_begin;
|
handler->beginFunc = script_phys_cb_begin;
|
||||||
handler->separateFunc = script_phys_cb_separate;
|
handler->separateFunc = script_phys_cb_separate;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,10 @@
|
||||||
|
|
||||||
#include "script.h"
|
#include "script.h"
|
||||||
#include <chipmunk/chipmunk.h>
|
#include <chipmunk/chipmunk.h>
|
||||||
|
#include "gameobject.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
|
|
||||||
struct gameobject;
|
|
||||||
|
|
||||||
extern float phys2d_gravity;
|
extern float phys2d_gravity;
|
||||||
extern int physOn;
|
extern int physOn;
|
||||||
extern cpSpace *space;
|
extern cpSpace *space;
|
||||||
|
@ -24,7 +23,7 @@ extern struct rgba sleep_color;
|
||||||
struct phys2d_shape {
|
struct phys2d_shape {
|
||||||
cpShape *shape;
|
cpShape *shape;
|
||||||
transform2d t;
|
transform2d t;
|
||||||
int go;
|
gameobject *go;
|
||||||
void *data; /* The specific subtype; phys2d_circle, etc */
|
void *data; /* The specific subtype; phys2d_circle, etc */
|
||||||
void (*debugdraw)(void *data);
|
void (*debugdraw)(void *data);
|
||||||
float (*moi)(void *data, float mass);
|
float (*moi)(void *data, float mass);
|
||||||
|
@ -71,19 +70,19 @@ struct phys2d_edge {
|
||||||
int draws;
|
int draws;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct phys2d_circle *Make2DCircle(int go);
|
struct phys2d_circle *Make2DCircle(gameobject *go);
|
||||||
void phys2d_circledel(struct phys2d_circle *c);
|
void phys2d_circledel(struct phys2d_circle *c);
|
||||||
void phys2d_applycircle(struct phys2d_circle *circle);
|
void phys2d_applycircle(struct phys2d_circle *circle);
|
||||||
void phys2d_dbgdrawcircle(struct phys2d_circle *circle);
|
void phys2d_dbgdrawcircle(struct phys2d_circle *circle);
|
||||||
float phys2d_circle_moi(struct phys2d_circle *c, float m);
|
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_boxdel(struct phys2d_box *box);
|
||||||
void phys2d_applybox(struct phys2d_box *box);
|
void phys2d_applybox(struct phys2d_box *box);
|
||||||
void phys2d_dbgdrawbox(struct phys2d_box *box);
|
void phys2d_dbgdrawbox(struct phys2d_box *box);
|
||||||
float phys2d_box_moi(struct phys2d_box *box, float m);
|
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_polydel(struct phys2d_poly *poly);
|
||||||
void phys2d_applypoly(struct phys2d_poly *poly);
|
void phys2d_applypoly(struct phys2d_poly *poly);
|
||||||
void phys2d_dbgdrawpoly(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);
|
void phys2d_poly_setverts(struct phys2d_poly *poly, cpVect *verts);
|
||||||
float phys2d_poly_moi(struct phys2d_poly *poly, float m);
|
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_edgedel(struct phys2d_edge *edge);
|
||||||
void phys2d_applyedge(struct phys2d_edge *edge);
|
void phys2d_applyedge(struct phys2d_edge *edge);
|
||||||
void phys2d_dbgdrawedge(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_init();
|
||||||
void phys2d_update(float deltaT);
|
void phys2d_update(float deltaT);
|
||||||
cpShape *phys2d_query_pos(cpVect pos);
|
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 shape_cb {
|
||||||
struct phys2d_shape *shape;
|
struct phys2d_shape *shape;
|
||||||
|
@ -122,7 +117,7 @@ struct shape_cb {
|
||||||
|
|
||||||
void fire_hits();
|
void fire_hits();
|
||||||
|
|
||||||
void phys2d_rm_go_handlers(int go);
|
void phys2d_rm_go_handlers(gameobject *go);
|
||||||
void phys2d_set_gravity(cpVect v);
|
void phys2d_set_gravity(cpVect v);
|
||||||
|
|
||||||
void shape_enabled(struct phys2d_shape *shape, int enabled);
|
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);
|
struct rgba shape_color_s(cpShape *shape);
|
||||||
|
|
||||||
void shape_gui(struct phys2d_shape *shape);
|
void shape_gui(struct phys2d_shape *shape);
|
||||||
void phys2d_setup_handlers(int go);
|
void phys2d_setup_handlers(gameobject *go);
|
||||||
int *phys2d_query_shape(struct phys2d_shape *shape);
|
gameobject *phys2d_query_shape(struct phys2d_shape *shape);
|
||||||
int *phys2d_query_box_points(HMM_Vec2 pos, HMM_Vec2 wh, HMM_Vec2 *points, int n);
|
int *phys2d_query_box_points(HMM_Vec2 pos, HMM_Vec2 wh, HMM_Vec2 *points, int n);
|
||||||
|
|
||||||
void flush_collide_cbs();
|
void flush_collide_cbs();
|
||||||
|
|
|
@ -390,7 +390,7 @@ struct drawmodel *make_drawmodel(int go)
|
||||||
void draw_drawmodel(struct drawmodel *dm)
|
void draw_drawmodel(struct drawmodel *dm)
|
||||||
{
|
{
|
||||||
if (!dm->model) return;
|
if (!dm->model) return;
|
||||||
struct gameobject *go = id2go(dm->go);
|
struct gameobject *go = dm->go;
|
||||||
HMM_Mat4 rst = t3d_go2world(go);
|
HMM_Mat4 rst = t3d_go2world(go);
|
||||||
draw_model(dm->model, rst);
|
draw_model(dm->model, rst);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "HandmadeMath.h"
|
#include "HandmadeMath.h"
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
#include "sokol/sokol_gfx.h"
|
#include "sokol/sokol_gfx.h"
|
||||||
|
#include "gameobject.h"
|
||||||
|
|
||||||
extern HMM_Vec3 eye;
|
extern HMM_Vec3 eye;
|
||||||
struct shader;
|
struct shader;
|
||||||
|
@ -32,7 +33,7 @@ typedef struct model {
|
||||||
struct drawmodel {
|
struct drawmodel {
|
||||||
struct model *model;
|
struct model *model;
|
||||||
HMM_Mat4 amodel;
|
HMM_Mat4 amodel;
|
||||||
int go;
|
gameobject *go;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct bone {
|
typedef struct bone {
|
||||||
|
|
|
@ -1,61 +1,35 @@
|
||||||
#include "gameobject.h"
|
#include "gameobject.h"
|
||||||
|
|
||||||
#include "2dphysics.h"
|
#include "2dphysics.h"
|
||||||
#include "log.h"
|
|
||||||
#include <chipmunk/chipmunk.h>
|
#include <chipmunk/chipmunk.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "debugdraw.h"
|
#include "debugdraw.h"
|
||||||
#include "freelist.h"
|
#include "log.h"
|
||||||
|
|
||||||
#include "stb_ds.h"
|
#include "stb_ds.h"
|
||||||
|
|
||||||
struct gameobject *gameobjects = NULL;
|
gameobject *body2go(cpBody *body) { return cpBodyGetUserData(body); }
|
||||||
|
gameobject *shape2go(cpShape *shape)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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);
|
cpVect p = cpBodyGetPosition(go->body);
|
||||||
return (HMM_Vec2){p.x, p.y};
|
return (HMM_Vec2){p.x, p.y};
|
||||||
}
|
}
|
||||||
|
|
||||||
HMM_Vec2 go_worldpos(struct gameobject *go)
|
HMM_Vec2 go_worldpos(gameobject *go)
|
||||||
{
|
{
|
||||||
HMM_Vec2 ret;
|
HMM_Vec2 ret;
|
||||||
ret.cp = cpBodyGetPosition(go->body);
|
ret.cp = cpBodyGetPosition(go->body);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
float go_angle(struct gameobject *go) { return go_worldangle(go); }
|
float go_angle(gameobject *go) { return go_worldangle(go); }
|
||||||
|
float go_worldangle(gameobject *go) { return cpBodyGetAngle(go->body); }
|
||||||
float go_worldangle(struct gameobject *go) { return cpBodyGetAngle(go->body); }
|
float go2angle(gameobject *go) { return cpBodyGetAngle(go->body); }
|
||||||
|
|
||||||
float go2angle(struct gameobject *go) { return cpBodyGetAngle(go->body); }
|
|
||||||
|
|
||||||
transform3d go2t3(gameobject *go)
|
transform3d go2t3(gameobject *go)
|
||||||
{
|
{
|
||||||
|
@ -72,23 +46,21 @@ transform3d go2t3(gameobject *go)
|
||||||
return t;
|
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); }
|
gameobject *pos2gameobject(HMM_Vec2 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) {
|
|
||||||
cpShape *hit = phys2d_query_pos(pos.cp);
|
cpShape *hit = phys2d_query_pos(pos.cp);
|
||||||
|
|
||||||
if (hit)
|
if (hit)
|
||||||
return shape2gameobject(hit);
|
return shape2go(hit);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
/*
|
||||||
for (int i = 0; i < arrlen(gameobjects); i++) {
|
for (int i = 0; i < arrlen(gameobjects); i++) {
|
||||||
if (!gameobjects[i].body) continue;
|
if (!gameobjects[i].body) continue;
|
||||||
cpVect gpos = cpBodyGetPosition(gameobjects[i].body);
|
cpVect gpos = cpBodyGetPosition(gameobjects[i].body);
|
||||||
|
@ -96,8 +68,8 @@ int pos2gameobject(HMM_Vec2 pos) {
|
||||||
|
|
||||||
if (dist <= 25) return i;
|
if (dist <= 25) return i;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
transform2d go2t(gameobject *go)
|
transform2d go2t(gameobject *go)
|
||||||
|
@ -111,22 +83,15 @@ transform2d go2t(gameobject *go)
|
||||||
return t;
|
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;
|
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);
|
cpShapeSetFriction(shape, go->f);
|
||||||
cpShapeSetElasticity(shape, go->e);
|
cpShapeSetElasticity(shape, go->e);
|
||||||
cpShapeSetCollisionType(shape, go2id(go));
|
cpShapeSetCollisionType(shape, go);
|
||||||
|
|
||||||
cpShapeFilter filter;
|
cpShapeFilter filter;
|
||||||
filter.group = go2id(go);
|
filter.group = go;
|
||||||
filter.categories = 1<<go->layer | editor_cat;
|
filter.categories = 1<<go->layer | editor_cat;
|
||||||
// filter.mask = CP_ALL_CATEGORIES;
|
// filter.mask = CP_ALL_CATEGORIES;
|
||||||
filter.mask = category_masks[go->layer] | editor_cat;
|
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);
|
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);
|
float moment = cpBodyGetMoment(go->body);
|
||||||
struct phys2d_shape *s = cpShapeGetUserData(shape);
|
struct phys2d_shape *s = cpShapeGetUserData(shape);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
|
@ -151,7 +116,7 @@ void go_shape_moi(cpBody *body, cpShape *shape, struct gameobject *go) {
|
||||||
cpBodySetMoment(go->body, 1);
|
cpBodySetMoment(go->body, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gameobject_apply(struct gameobject *go) {
|
void gameobject_apply(gameobject *go) {
|
||||||
cpBodySetType(go->body, go->bodytype);
|
cpBodySetType(go->body, go->bodytype);
|
||||||
cpBodyEachShape(go->body, go_shape_apply, go);
|
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)
|
static void velocityFn(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
|
||||||
{
|
{
|
||||||
struct gameobject *go = id2go((int)cpBodyGetUserData(body));
|
gameobject *go = body2go(body);
|
||||||
if (!go) {
|
if (!go) {
|
||||||
cpBodyUpdateVelocity(body,gravity,damping,dt);
|
cpBodyUpdateVelocity(body,gravity,damping,dt);
|
||||||
return;
|
return;
|
||||||
|
@ -190,8 +155,9 @@ static void velocityFn(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int MakeGameobject() {
|
gameobject *MakeGameobject() {
|
||||||
struct gameobject go = {
|
gameobject *ngo = malloc(sizeof(*ngo));
|
||||||
|
gameobject go = {
|
||||||
.scale = (HMM_Vec3){1.f,1.f,1.f},
|
.scale = (HMM_Vec3){1.f,1.f,1.f},
|
||||||
.bodytype = CP_BODY_TYPE_STATIC,
|
.bodytype = CP_BODY_TYPE_STATIC,
|
||||||
.maxvelocity = INFINITY,
|
.maxvelocity = INFINITY,
|
||||||
|
@ -206,6 +172,8 @@ int MakeGameobject() {
|
||||||
.damping = NAN,
|
.damping = NAN,
|
||||||
.timescale = 1.0,
|
.timescale = 1.0,
|
||||||
.ref = JS_UNDEFINED,
|
.ref = JS_UNDEFINED,
|
||||||
|
.parent = NULL,
|
||||||
|
.children = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
go.cbs.begin.obj = JS_UNDEFINED;
|
go.cbs.begin.obj = JS_UNDEFINED;
|
||||||
|
@ -214,16 +182,13 @@ int MakeGameobject() {
|
||||||
go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f));
|
go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f));
|
||||||
cpBodySetVelocityUpdateFunc(go.body, velocityFn);
|
cpBodySetVelocityUpdateFunc(go.body, velocityFn);
|
||||||
|
|
||||||
int id;
|
*ngo = go;
|
||||||
if (!gameobjects) freelist_size(gameobjects,500);
|
cpBodySetUserData(go.body, ngo);
|
||||||
freelist_grab(id, gameobjects);
|
phys2d_setup_handlers(ngo);
|
||||||
cpBodySetUserData(go.body, (void*)id);
|
return ngo;
|
||||||
phys2d_setup_handlers(id);
|
|
||||||
gameobjects[id] = go;
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gameobject_traverse(struct gameobject *go, HMM_Mat4 p)
|
void gameobject_traverse(gameobject *go, HMM_Mat4 p)
|
||||||
{
|
{
|
||||||
HMM_Mat4 local = transform3d2mat(go2t3(go));
|
HMM_Mat4 local = transform3d2mat(go2t3(go));
|
||||||
go->world = HMM_MulM4(local, p);
|
go->world = HMM_MulM4(local, p);
|
||||||
|
@ -242,36 +207,30 @@ void rm_body_shapes(cpBody *body, cpShape *shape, void *data) {
|
||||||
cpShapeFree(shape);
|
cpShapeFree(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
int *go_toclean = NULL;
|
gameobject **go_toclean = NULL;
|
||||||
|
|
||||||
/* Free this gameobject */
|
/* Free this gameobject */
|
||||||
void gameobject_clean(int id) {
|
void gameobject_clean(gameobject *go) {
|
||||||
struct gameobject *go = id2go(id);
|
|
||||||
arrfree(go->shape_cbs);
|
arrfree(go->shape_cbs);
|
||||||
cpBodyEachShape(go->body, rm_body_shapes, NULL);
|
cpBodyEachShape(go->body, rm_body_shapes, NULL);
|
||||||
cpSpaceRemoveBody(space, go->body);
|
cpSpaceRemoveBody(space, go->body);
|
||||||
cpBodyFree(go->body);
|
cpBodyFree(go->body);
|
||||||
go->body = NULL;
|
go->body = NULL;
|
||||||
|
|
||||||
|
free(go);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Really more of a "mark for deletion" ... */
|
/* Really more of a "mark for deletion" ... */
|
||||||
void gameobject_delete(int id) {
|
void gameobject_free(gameobject *go) {
|
||||||
gameobject *go = id2go(id);
|
if (!go) return;
|
||||||
|
YughWarn("FREEING A GAMEOBJECT");
|
||||||
JS_FreeValue(js, go->ref);
|
JS_FreeValue(js, go->ref);
|
||||||
|
dag_clip(go);
|
||||||
|
|
||||||
if (cpSpaceIsLocked(space))
|
if (cpSpaceIsLocked(space))
|
||||||
arrpush(go_toclean, id);
|
arrpush(go_toclean, go);
|
||||||
else
|
else
|
||||||
gameobject_clean(id);
|
gameobject_clean(go);
|
||||||
|
|
||||||
dag_clip(go);
|
|
||||||
freelist_kill(gameobjects,id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gameobject_free(int id)
|
|
||||||
{
|
|
||||||
if (id >= 0)
|
|
||||||
gameobject_delete(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gameobjects_cleanup() {
|
void gameobjects_cleanup() {
|
||||||
|
@ -281,12 +240,12 @@ void gameobjects_cleanup() {
|
||||||
arrsetlen(go_toclean, 0);
|
arrsetlen(go_toclean, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gameobject_setangle(struct gameobject *go, float angle) {
|
void gameobject_setangle(gameobject *go, float angle) {
|
||||||
cpBodySetAngle(go->body, angle);
|
cpBodySetAngle(go->body, angle);
|
||||||
phys2d_reindex_body(go->body);
|
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;
|
if (!go || !go->body) return;
|
||||||
cpBodySetPosition(go->body, vec);
|
cpBodySetPosition(go->body, vec);
|
||||||
phys2d_reindex_body(go->body);
|
phys2d_reindex_body(go->body);
|
||||||
|
@ -297,15 +256,9 @@ void body_draw_shapes_dbg(cpBody *body, cpShape *shape, void *data) {
|
||||||
s->debugdraw(s->data);
|
s->debugdraw(s->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gameobject_draw_debug(int go) {
|
void gameobject_draw_debug(gameobject *go) {
|
||||||
struct gameobject *g = id2go(go);
|
if (!go || !go->body) return;
|
||||||
if (!g || !g->body) return;
|
|
||||||
|
|
||||||
cpVect pos = cpBodyGetPosition(g->body);
|
cpVect pos = cpBodyGetPosition(go->body);
|
||||||
cpBodyEachShape(g->body, body_draw_shapes_dbg, NULL);
|
cpBodyEachShape(go->body, body_draw_shapes_dbg, NULL);
|
||||||
}
|
|
||||||
|
|
||||||
void gameobject_draw_debugs() {
|
|
||||||
for (int i = 0; i < arrlen(gameobjects); i++)
|
|
||||||
gameobject_draw_debug(i);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#ifndef GAMEOBJECT_H
|
#ifndef GAMEOBJECT_H
|
||||||
#define GAMEOBJECT_H
|
#define GAMEOBJECT_H
|
||||||
|
|
||||||
#include "2dphysics.h"
|
|
||||||
#include <chipmunk/chipmunk.h>
|
#include <chipmunk/chipmunk.h>
|
||||||
#include "quickjs/quickjs.h"
|
#include "quickjs/quickjs.h"
|
||||||
#include "HandmadeMath.h"
|
#include "HandmadeMath.h"
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
|
#include "script.h"
|
||||||
|
|
||||||
#define dag_rm(p,c) do{\
|
#define dag_rm(p,c) do{\
|
||||||
for (int i = arrlen(p->children)-1; i--; i >=0) {\
|
for (int i = arrlen(p->children)-1; i--; i >=0) {\
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
dag_rm(p->parent,p);\
|
dag_rm(p->parent,p);\
|
||||||
}while(0)
|
}while(0)
|
||||||
|
|
||||||
typedef struct gameobject {
|
struct gameobject {
|
||||||
cpBodyType bodytype;
|
cpBodyType bodytype;
|
||||||
cpBody *body; /* NULL if this object is dead; has 2d position and rotation, relative to global 0 */
|
cpBody *body; /* NULL if this object is dead; has 2d position and rotation, relative to global 0 */
|
||||||
HMM_Vec3 scale; /* local */
|
HMM_Vec3 scale; /* local */
|
||||||
|
@ -51,53 +51,46 @@ typedef struct gameobject {
|
||||||
float drawlayer;
|
float drawlayer;
|
||||||
struct gameobject *parent;
|
struct gameobject *parent;
|
||||||
struct gameobject **children;
|
struct gameobject **children;
|
||||||
} gameobject;
|
};
|
||||||
|
|
||||||
extern struct gameobject *gameobjects;
|
typedef struct gameobject gameobject;
|
||||||
|
|
||||||
int MakeGameobject();
|
gameobject *MakeGameobject();
|
||||||
void gameobject_apply(struct gameobject *go);
|
void gameobject_apply(gameobject *go);
|
||||||
void gameobject_delete(int id);
|
void gameobject_free(gameobject *go);
|
||||||
void gameobject_free(int id);
|
|
||||||
void gameobjects_cleanup();
|
void gameobjects_cleanup();
|
||||||
|
|
||||||
void gameobject_traverse(struct gameobject *start, HMM_Mat4 p);
|
void gameobject_traverse(gameobject *start, HMM_Mat4 p);
|
||||||
|
|
||||||
transform2d go2t(gameobject *go);
|
transform2d go2t(gameobject *go);
|
||||||
transform3d go2t3(gameobject *go);
|
transform3d go2t3(gameobject *go);
|
||||||
|
|
||||||
HMM_Vec2 go2world(struct gameobject *go, HMM_Vec2 pos);
|
HMM_Vec2 go2world(gameobject *go, HMM_Vec2 pos);
|
||||||
HMM_Vec2 world2go(struct gameobject *go, HMM_Vec2 pos);
|
HMM_Vec2 world2go(gameobject *go, HMM_Vec2 pos);
|
||||||
|
|
||||||
HMM_Mat3 t_go2world(struct gameobject *go);
|
HMM_Mat3 t_go2world(gameobject *go);
|
||||||
HMM_Mat3 t_world2go(struct gameobject *go);
|
HMM_Mat3 t_world2go(gameobject *go);
|
||||||
HMM_Mat4 t3d_go2world(struct gameobject *go);
|
HMM_Mat4 t3d_go2world(gameobject *go);
|
||||||
HMM_Mat4 t3d_world2go(struct gameobject *go);
|
HMM_Mat4 t3d_world2go(gameobject *go);
|
||||||
|
|
||||||
HMM_Vec2 go_pos(struct gameobject *go);
|
HMM_Vec2 go_pos(gameobject *go);
|
||||||
HMM_Vec2 go_worldpos(struct gameobject *go);
|
HMM_Vec2 go_worldpos(gameobject *go);
|
||||||
//float go_angle(struct gameobject *go);
|
//float go_angle(gameobject *go);
|
||||||
float go_worldangle(struct gameobject *go);
|
float go_worldangle(gameobject *go);
|
||||||
|
|
||||||
float go2angle(struct gameobject *go);
|
float go2angle(gameobject *go);
|
||||||
|
|
||||||
struct gameobject *id2go(int id);
|
gameobject *body2go(cpBody *body);
|
||||||
int go2id(struct gameobject *go);
|
gameobject *shape2go(cpShape *shape);
|
||||||
int body2id(cpBody *body);
|
|
||||||
cpBody *id2body(int id);
|
|
||||||
int shape2gameobject(cpShape *shape);
|
|
||||||
struct 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 */
|
/* 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_move(gameobject *go, HMM_Vec2 vec);
|
||||||
void gameobject_rotate(struct gameobject *go, float as);
|
void gameobject_rotate(gameobject *go, float as);
|
||||||
void gameobject_setangle(struct gameobject *go, float angle);
|
void gameobject_setangle(gameobject *go, float angle);
|
||||||
void gameobject_setpos(struct gameobject *go, cpVect vec);
|
void gameobject_setpos(gameobject *go, cpVect vec);
|
||||||
|
void gameobject_draw_debug(gameobject *go);
|
||||||
void gameobject_draw_debugs();
|
|
||||||
void gameobject_draw_debug(int go);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
#include "gameobject.h"
|
#include "gameobject.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "level.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "dsp.h"
|
#include "dsp.h"
|
||||||
#include "music.h"
|
#include "music.h"
|
||||||
|
@ -51,11 +50,8 @@ static JSValue TYPE##2js(TYPE *n) { \
|
||||||
JS_SetOpaque(j,n);\
|
JS_SetOpaque(j,n);\
|
||||||
return j; }\
|
return j; }\
|
||||||
|
|
||||||
|
|
||||||
QJSCLASS(dsp_node)
|
QJSCLASS(dsp_node)
|
||||||
|
|
||||||
// gameobject2js, js2gameobject deals with gameobject*, converted to ids
|
|
||||||
// go2js,js2go deals with gameobject*
|
|
||||||
|
|
||||||
QJSCLASS(gameobject)
|
QJSCLASS(gameobject)
|
||||||
|
|
||||||
#define QJSCLASSPREP(TYPE) \
|
#define QJSCLASSPREP(TYPE) \
|
||||||
|
@ -123,22 +119,13 @@ JSValue jscurtime()
|
||||||
return jst;
|
return jst;
|
||||||
}
|
}
|
||||||
|
|
||||||
void js_setprop_num(JSValue obj, uint32_t i, JSValue v)
|
void js_setprop_num(JSValue obj, uint32_t i, JSValue v) { JS_SetPropertyUint32(js, obj, i, v); }
|
||||||
{
|
|
||||||
JS_SetPropertyUint32(js, obj, i, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue go2ref(int id)
|
JSValue gos2ref(gameobject **go)
|
||||||
{
|
|
||||||
if (id == -1) return JS_UNDEFINED;
|
|
||||||
return JS_DupValue(js,id2go(id)->ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue gos2ref(int *go)
|
|
||||||
{
|
{
|
||||||
JSValue array = JS_NewArray(js);
|
JSValue array = JS_NewArray(js);
|
||||||
for (int i = 0; i < arrlen(go); i++)
|
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;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,26 +185,11 @@ double js2number(JSValue v) {
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSValue float2js(double g) { return JS_NewFloat64(js, g);}
|
||||||
JSValue float2js(double g) {
|
JSValue num2js(double g) { return float2js(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)); }
|
|
||||||
|
|
||||||
struct sprite *js2sprite(JSValue v) { return id2sprite(js2int(v)); }
|
struct sprite *js2sprite(JSValue v) { return id2sprite(js2int(v)); }
|
||||||
|
|
||||||
void *js2ptr(JSValue v) {
|
void *js2ptr(JSValue v) { return JS_GetOpaque(v,js_ptr_id); }
|
||||||
return JS_GetOpaque(v,js_ptr_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue ptr2js(void *ptr) {
|
JSValue ptr2js(void *ptr) {
|
||||||
JSValue obj = JS_NewObjectClass(js, js_ptr_id);
|
JSValue obj = JS_NewObjectClass(js, js_ptr_id);
|
||||||
|
@ -225,9 +197,7 @@ JSValue ptr2js(void *ptr) {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct timer *js2timer(JSValue v) {
|
struct timer *js2timer(JSValue v) { return id2timer(js2int(v)); }
|
||||||
return id2timer(js2int(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
double js_get_prop_number(JSValue v, const char *p) {
|
double js_get_prop_number(JSValue v, const char *p) {
|
||||||
double num;
|
double num;
|
||||||
|
@ -244,9 +214,7 @@ struct glrect js2glrect(JSValue v) {
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSValue js_arridx(JSValue v, int idx) {
|
JSValue js_arridx(JSValue v, int idx) { return js_getpropidx( v, idx); }
|
||||||
return js_getpropidx( v, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int js_arrlen(JSValue v) {
|
int js_arrlen(JSValue v) {
|
||||||
int len;
|
int len;
|
||||||
|
@ -541,6 +509,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
const void *d1 = NULL;
|
const void *d1 = NULL;
|
||||||
const void *d2 = NULL;
|
const void *d2 = NULL;
|
||||||
int *ids = NULL;
|
int *ids = NULL;
|
||||||
|
gameobject *go = NULL;
|
||||||
JSValue ret = JS_UNDEFINED;
|
JSValue ret = JS_UNDEFINED;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
@ -555,9 +524,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
YughWarn("Deleting gameobject %d", js2int(argv[1]));
|
gameobject_free(js2int(argv[1]));
|
||||||
gameobject_delete(js2int(argv[1]));
|
|
||||||
YughWarn("Deleted gameobject %d", js2int(argv[1]));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
|
@ -699,9 +666,9 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 36:
|
case 36:
|
||||||
js2go(argv[1])->scale.XY = js2vec2(argv[2]);
|
js2gameobject(argv[1])->scale.XY = js2vec2(argv[2]);
|
||||||
gameobject_apply(js2go(argv[1]));
|
gameobject_apply(js2gameobject(argv[1]));
|
||||||
cpSpaceReindexShapesForBody(space, js2go(argv[1])->body);
|
cpSpaceReindexShapesForBody(space, js2gameobject(argv[1])->body);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 37:
|
case 37:
|
||||||
|
@ -722,25 +689,26 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 40:
|
case 40:
|
||||||
js2go(argv[1])->filter.categories = js2bitmask(argv[2]);
|
js2gameobject(argv[1])->filter.categories = js2bitmask(argv[2]);
|
||||||
gameobject_apply(js2go(argv[1]));
|
gameobject_apply(js2gameobject(argv[1]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 41:
|
case 41:
|
||||||
js2go(argv[1])->filter.mask = js2bitmask(argv[2]);
|
js2gameobject(argv[1])->filter.mask = js2bitmask(argv[2]);
|
||||||
gameobject_apply(js2go(argv[1]));
|
gameobject_apply(js2gameobject(argv[1]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 42:
|
case 42:
|
||||||
ret = bitmask2js(js2go(argv[1])->filter.categories);
|
ret = bitmask2js(js2gameobject(argv[1])->filter.categories);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 43:
|
case 43:
|
||||||
ret = bitmask2js(js2go(argv[1])->filter.mask);
|
ret = bitmask2js(js2gameobject(argv[1])->filter.mask);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 44:
|
case 44:
|
||||||
ret = go2ref(pos2gameobject(js2vec2(argv[1])));
|
go = pos2gameobject(js2vec2(argv[1]));
|
||||||
|
ret = go ? go->ref : JS_UNDEFINED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 45:
|
case 45:
|
||||||
|
@ -782,23 +750,23 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 54:
|
case 54:
|
||||||
gameobject_apply(js2go(argv[1]));
|
gameobject_apply(js2gameobject(argv[1]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 55:
|
case 55:
|
||||||
break;
|
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:
|
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;
|
break;
|
||||||
|
|
||||||
case 57:
|
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;
|
break;
|
||||||
|
|
||||||
case 58:
|
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;
|
break;
|
||||||
|
|
||||||
case 59:
|
case 59:
|
||||||
|
@ -811,7 +779,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 61:
|
case 61:
|
||||||
set_cam_body(id2body(js2int(argv[1])));
|
set_cam_body(js2gameobject(argv[1])->body);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 62:
|
case 62:
|
||||||
|
@ -847,11 +815,11 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 70:
|
case 70:
|
||||||
ret = vec2js(world2go(js2go(argv[1]), js2vec2(argv[2])));
|
ret = vec2js(world2go(js2gameobject(argv[1]), js2vec2(argv[2])));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 71:
|
case 71:
|
||||||
ret = vec2js(go2world(js2go(argv[1]), js2vec2(argv[2])));
|
ret = vec2js(go2world(js2gameobject(argv[1]), js2vec2(argv[2])));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 72:
|
case 72:
|
||||||
|
@ -867,7 +835,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 75:
|
case 75:
|
||||||
js2go(argv[1])->layer = js2int(argv[2]);
|
js2gameobject(argv[1])->layer = js2int(argv[2]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 76:
|
case 76:
|
||||||
|
@ -875,7 +843,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 77:
|
case 77:
|
||||||
ret = int2js(js2go(argv[1])->layer);
|
ret = int2js(js2gameobject(argv[1])->layer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 78:
|
case 78:
|
||||||
|
@ -896,7 +864,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 82:
|
case 82:
|
||||||
gameobject_draw_debug(js2go(argv[1]));
|
gameobject_draw_debug(js2gameobject(argv[1]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 83:
|
case 83:
|
||||||
|
@ -989,35 +957,35 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 103:
|
case 103:
|
||||||
ret = vec2js(js2go(argv[1])->scale.XY);
|
ret = vec2js(js2gameobject(argv[1])->scale.XY);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 104:
|
case 104:
|
||||||
// ret = bool2js(js2go(argv[1])->flipx == -1 ? 1 : 0);
|
// ret = bool2js(js2gameobject(argv[1])->flipx == -1 ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 105:
|
case 105:
|
||||||
// ret = bool2js(js2go(argv[1])->flipy == -1 ? 1 : 0);
|
// ret = bool2js(js2gameobject(argv[1])->flipy == -1 ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 106:
|
case 106:
|
||||||
js2go(argv[1])->e = js2number(argv[2]);
|
js2gameobject(argv[1])->e = js2number(argv[2]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 107:
|
case 107:
|
||||||
ret = num2js(js2go(argv[1])->e);
|
ret = num2js(js2gameobject(argv[1])->e);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 108:
|
case 108:
|
||||||
js2go(argv[1])->f = js2number(argv[2]);
|
js2gameobject(argv[1])->f = js2number(argv[2]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 109:
|
case 109:
|
||||||
ret = num2js(js2go(argv[1])->f);
|
ret = num2js(js2gameobject(argv[1])->f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 110:
|
case 110:
|
||||||
ret = num2js(js2go(argv[1])->e);
|
ret = num2js(js2gameobject(argv[1])->e);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 111:
|
case 111:
|
||||||
|
@ -1029,7 +997,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 113:
|
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;
|
break;
|
||||||
|
|
||||||
case 114:
|
case 114:
|
||||||
|
@ -1188,38 +1156,38 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 151:
|
case 151:
|
||||||
js2go(argv[1])->maxvelocity = js2number(argv[2]);
|
js2gameobject(argv[1])->maxvelocity = js2number(argv[2]);
|
||||||
break;
|
break;
|
||||||
case 152:
|
case 152:
|
||||||
ret = num2js(js2go(argv[1])->maxvelocity);
|
ret = num2js(js2gameobject(argv[1])->maxvelocity);
|
||||||
break;
|
break;
|
||||||
case 153:
|
case 153:
|
||||||
cpBodySetTorque(js2go(argv[1])->body, js2number(argv[2]));
|
cpBodySetTorque(js2gameobject(argv[1])->body, js2number(argv[2]));
|
||||||
break;
|
break;
|
||||||
case 154:
|
case 154:
|
||||||
js2go(argv[1])->maxangularvelocity = js2number(argv[2]);
|
js2gameobject(argv[1])->maxangularvelocity = js2number(argv[2]);
|
||||||
break;
|
break;
|
||||||
case 155:
|
case 155:
|
||||||
ret = num2js(js2go(argv[1])->maxangularvelocity);
|
ret = num2js(js2gameobject(argv[1])->maxangularvelocity);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 156:
|
case 156:
|
||||||
js2go(argv[1])->damping = js2number(argv[2]);
|
js2gameobject(argv[1])->damping = js2number(argv[2]);
|
||||||
break;
|
break;
|
||||||
case 157:
|
case 157:
|
||||||
ret = num2js(js2go(argv[1])->damping);
|
ret = num2js(js2gameobject(argv[1])->damping);
|
||||||
break;
|
break;
|
||||||
case 158:
|
case 158:
|
||||||
js2go(argv[1])->gravity = js2bool(argv[2]);
|
js2gameobject(argv[1])->gravity = js2bool(argv[2]);
|
||||||
break;
|
break;
|
||||||
case 159:
|
case 159:
|
||||||
ret = bool2js(js2go(argv[1])->gravity);
|
ret = bool2js(js2gameobject(argv[1])->gravity);
|
||||||
break;
|
break;
|
||||||
case 160:
|
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;
|
break;
|
||||||
case 161:
|
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;
|
break;
|
||||||
case 162:
|
case 162:
|
||||||
str = JS_ToCString(js, argv[1]);
|
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));
|
ret = int2js(cp(str, str2));
|
||||||
break;
|
break;
|
||||||
case 167:
|
case 167:
|
||||||
js2go(argv[1])->cgravity = js2vec2(argv[2]);
|
js2gameobject(argv[1])->cgravity = js2vec2(argv[2]);
|
||||||
break;
|
break;
|
||||||
case 168:
|
case 168:
|
||||||
js2go(argv[1])->timescale = js2number(argv[2]);
|
js2gameobject(argv[1])->timescale = js2number(argv[2]);
|
||||||
break;
|
break;
|
||||||
case 169:
|
case 169:
|
||||||
ret = num2js(js2go(argv[1])->timescale);
|
ret = num2js(js2gameobject(argv[1])->timescale);
|
||||||
break;
|
break;
|
||||||
case 170:
|
case 170:
|
||||||
id2sprite(js2int(argv[1]))->emissive = js2color(argv[2]);
|
id2sprite(js2int(argv[1]))->emissive = js2color(argv[2]);
|
||||||
break;
|
break;
|
||||||
case 171:
|
case 171:
|
||||||
ret = num2js(js2go(argv[1])->drawlayer);
|
ret = num2js(js2gameobject(argv[1])->drawlayer);
|
||||||
break;
|
break;
|
||||||
case 172:
|
case 172:
|
||||||
js2go(argv[1])->drawlayer = js2number(argv[2]);
|
js2gameobject(argv[1])->drawlayer = js2number(argv[2]);
|
||||||
break;
|
break;
|
||||||
case 173:
|
case 173:
|
||||||
str = js2str(argv[1]);
|
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])));
|
ret = dsp_node2js(dsp_fwd_delay(js2number(argv[1]), js2number(argv[2])));
|
||||||
break;
|
break;
|
||||||
case 208:
|
case 208:
|
||||||
dag_set(js2go(argv[1]), js2go(argv[2]));
|
dag_set(js2gameobject(argv[1]), js2gameobject(argv[2]));
|
||||||
break;
|
break;
|
||||||
case 209:
|
case 209:
|
||||||
ret = unix2time(js2number(argv[1]));
|
ret = unix2time(js2number(argv[1]));
|
||||||
|
@ -1460,23 +1428,23 @@ JSValue duk_register(JSContext *js, JSValueConst this, int argc, JSValueConst *a
|
||||||
return JS_UNDEFINED;
|
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;
|
struct shape_cb shapecb;
|
||||||
shapecb.shape = shape;
|
shapecb.shape = shape;
|
||||||
shapecb.cbs.begin = c;
|
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) {
|
JSValue duk_register_collide(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
||||||
int cmd = js2int(argv[0]);
|
int cmd = js2int(argv[0]);
|
||||||
int go = jsgo2id(argv[3]);
|
gameobject *go = js2gameobject(argv[3]);
|
||||||
struct callee c;
|
struct callee c;
|
||||||
c.fn = argv[1];
|
c.fn = argv[1];
|
||||||
c.obj = argv[2];
|
c.obj = argv[2];
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case 0:
|
case 0:
|
||||||
id2go(go)->cbs.begin = c;
|
go->cbs.begin = c;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -1488,7 +1456,7 @@ JSValue duk_register_collide(JSContext *js, JSValueConst this, int argc, JSValue
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
id2go(go)->cbs.separate = c;
|
go->cbs.separate = c;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1533,7 +1501,6 @@ JSValue duk_sys_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *ar
|
||||||
return JS_NewInt64(js, frame_fps());
|
return JS_NewInt64(js, frame_fps());
|
||||||
|
|
||||||
case 9: /* Clear the level out */
|
case 9: /* Clear the level out */
|
||||||
new_level();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 10:
|
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) {
|
JSValue duk_make_gameobject(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
||||||
|
YughWarn("MAKING GAMOBJECT");
|
||||||
return gameobject2js(MakeGameobject());
|
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) {
|
JSValue duk_set_body(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
||||||
int cmd = js2int(argv[0]);
|
int cmd = js2int(argv[0]);
|
||||||
struct gameobject *go = js2go(argv[1]);
|
gameobject *go = js2gameobject(argv[1]);
|
||||||
|
|
||||||
if (!go) return JS_UNDEFINED;
|
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) {
|
JSValue duk_q_body(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
||||||
int q = js2int(argv[0]);
|
int q = js2int(argv[0]);
|
||||||
struct gameobject *go = js2go(argv[1]);
|
gameobject *go = js2gameobject(argv[1]);
|
||||||
|
|
||||||
if (!go) return JS_UNDEFINED;
|
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));
|
return JS_NewBool(js, phys2d_in_air(go->body));
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
gameobject_delete(go2id(go));
|
gameobject_free(go);
|
||||||
break;
|
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) {
|
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]);
|
HMM_Vec2 size = js2vec2(argv[1]);
|
||||||
|
|
||||||
struct phys2d_box *box = Make2DBox(go);
|
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) {
|
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);
|
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)
|
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);
|
struct drawmodel *dm = make_drawmodel(go);
|
||||||
JSValue ret = JS_NewObject(js);
|
JSValue ret = JS_NewObject(js);
|
||||||
js_setprop_str(ret, "id", ptr2js(dm));
|
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) {
|
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);
|
struct phys2d_poly *poly = Make2DPoly(go);
|
||||||
phys2d_poly_setverts(poly, NULL);
|
phys2d_poly_setverts(poly, NULL);
|
||||||
JSValue polyval = JS_NewObject(js);
|
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) {
|
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);
|
struct phys2d_edge *edge = Make2DEdge(go);
|
||||||
|
|
||||||
int n = js_arrlen(argv[1]);
|
int n = js_arrlen(argv[1]);
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
#include "level.h"
|
|
||||||
#include "gameobject.h"
|
|
||||||
#include "resources.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -518,10 +518,9 @@ void full_2d_pass(struct window *window)
|
||||||
call_draw();
|
call_draw();
|
||||||
|
|
||||||
//// DEBUG
|
//// DEBUG
|
||||||
if (debugDrawPhysics) {
|
if (debugDrawPhysics)
|
||||||
gameobject_draw_debugs();
|
|
||||||
call_debugs();
|
call_debugs();
|
||||||
}
|
|
||||||
debug_flush(&projection);
|
debug_flush(&projection);
|
||||||
text_flush(&projection);
|
text_flush(&projection);
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,12 @@ struct callee {
|
||||||
JSValue obj;
|
JSValue obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct phys_cbs {
|
||||||
|
struct callee begin;
|
||||||
|
struct callee separate;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
extern struct callee stacktrace_callee;
|
extern struct callee stacktrace_callee;
|
||||||
extern JSValue num_cache[100];
|
extern JSValue num_cache[100];
|
||||||
|
|
||||||
|
|
334
source/engine/spline.c
Normal file
334
source/engine/spline.c
Normal file
|
@ -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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
22
source/engine/spline.h
Normal file
22
source/engine/spline.h
Normal file
|
@ -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
|
|
@ -108,8 +108,8 @@ void sprite_io(struct sprite *sprite, FILE *f, int read) {
|
||||||
|
|
||||||
int sprite_sort(int *a, int *b)
|
int sprite_sort(int *a, int *b)
|
||||||
{
|
{
|
||||||
struct gameobject *goa = id2go(sprites[*a].go);
|
struct gameobject *goa = sprites[*a].go;
|
||||||
struct gameobject *gob = id2go(sprites[*b].go);
|
struct gameobject *gob = sprites[*b].go;
|
||||||
if (goa->drawlayer == gob->drawlayer) return 0;
|
if (goa->drawlayer == gob->drawlayer) return 0;
|
||||||
if (goa->drawlayer > gob->drawlayer) return 1;
|
if (goa->drawlayer > gob->drawlayer) return 1;
|
||||||
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) {
|
void sprite_draw(struct sprite *sprite) {
|
||||||
struct gameobject *go = id2go(sprite->go);
|
gameobject *go = sprite->go;
|
||||||
|
|
||||||
if (sprite->tex) {
|
if (sprite->tex) {
|
||||||
HMM_Mat3 m = t_go2world(go);
|
HMM_Mat3 m = t_go2world(go);
|
||||||
|
|
|
@ -7,15 +7,13 @@
|
||||||
#include "HandmadeMath.h"
|
#include "HandmadeMath.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
|
#include "gameobject.h"
|
||||||
struct datastream;
|
|
||||||
struct gameobject;
|
|
||||||
|
|
||||||
struct sprite {
|
struct sprite {
|
||||||
transform2d t;
|
transform2d t;
|
||||||
struct rgba color;
|
struct rgba color;
|
||||||
struct rgba emissive;
|
struct rgba emissive;
|
||||||
int go; /* id of gameobject */
|
gameobject *go; /* id of gameobject */
|
||||||
struct Texture *tex;
|
struct Texture *tex;
|
||||||
struct glrect frame;
|
struct glrect frame;
|
||||||
int enabled;
|
int enabled;
|
||||||
|
|
|
@ -287,29 +287,12 @@ void c_event(const sapp_event *e)
|
||||||
|
|
||||||
int sim_playing() { return sim_play == SIM_PLAY; }
|
int sim_playing() { return sim_play == SIM_PLAY; }
|
||||||
int sim_paused() { return sim_play == SIM_PAUSE; }
|
int sim_paused() { return sim_play == SIM_PAUSE; }
|
||||||
|
void sim_start() { sim_play = SIM_PLAY; }
|
||||||
void sim_start() {
|
void sim_pause() { sim_play = SIM_PAUSE; }
|
||||||
sim_play = SIM_PLAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sim_pause() {
|
|
||||||
sim_play = SIM_PAUSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int phys_stepping() { return sim_play == SIM_STEP; }
|
int phys_stepping() { return sim_play == SIM_STEP; }
|
||||||
|
void sim_step() { sim_play = SIM_STEP; }
|
||||||
void sim_step() {
|
void set_timescale(float val) { timescale = val; }
|
||||||
sim_play = SIM_STEP;
|
double get_timescale() { return timescale; }
|
||||||
}
|
|
||||||
|
|
||||||
void set_timescale(float val) {
|
|
||||||
timescale = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
double get_timescale()
|
|
||||||
{
|
|
||||||
return timescale;
|
|
||||||
}
|
|
||||||
|
|
||||||
static sapp_desc start_desc = {
|
static sapp_desc start_desc = {
|
||||||
.width = 720,
|
.width = 720,
|
||||||
|
@ -330,10 +313,7 @@ static sapp_desc start_desc = {
|
||||||
.logger.func = sg_logging,
|
.logger.func = sg_logging,
|
||||||
};
|
};
|
||||||
|
|
||||||
void app_name(char *name)
|
void app_name(char *name) { start_desc.window_title = strdup(name); }
|
||||||
{
|
|
||||||
start_desc.window_title = strdup(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
Loading…
Reference in a new issue