spline
This commit is contained in:
parent
5ad3219379
commit
9fb36f5df3
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
|
||||
#include "script.h"
|
||||
#include <chipmunk/chipmunk.h>
|
||||
#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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -1,61 +1,35 @@
|
|||
#include "gameobject.h"
|
||||
|
||||
#include "2dphysics.h"
|
||||
#include "log.h"
|
||||
#include <chipmunk/chipmunk.h>
|
||||
#include <string.h>
|
||||
#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<<go->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);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#ifndef GAMEOBJECT_H
|
||||
#define GAMEOBJECT_H
|
||||
|
||||
#include "2dphysics.h"
|
||||
#include <chipmunk/chipmunk.h>
|
||||
#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
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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();
|
||||
|
||||
//// DEBUG
|
||||
if (debugDrawPhysics) {
|
||||
gameobject_draw_debugs();
|
||||
if (debugDrawPhysics)
|
||||
call_debugs();
|
||||
}
|
||||
|
||||
debug_flush(&projection);
|
||||
text_flush(&projection);
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
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)
|
||||
{
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue