2021-11-30 21:29:18 -06:00
|
|
|
#include "2dphysics.h"
|
|
|
|
|
|
|
|
#include "gameobject.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "mathc.h"
|
2022-08-12 14:03:56 -05:00
|
|
|
#include "nuke.h"
|
2023-01-27 12:06:16 -06:00
|
|
|
#include "debug.h"
|
2021-11-30 21:29:18 -06:00
|
|
|
|
2022-08-17 00:01:51 -05:00
|
|
|
#include "debugdraw.h"
|
|
|
|
#include "gameobject.h"
|
|
|
|
#include <math.h>
|
|
|
|
#include <chipmunk/chipmunk_unsafe.h>
|
2022-12-20 08:16:26 -06:00
|
|
|
#include "stb_ds.h"
|
2023-01-25 21:32:58 -06:00
|
|
|
#include <assert.h>
|
2022-12-20 08:16:26 -06:00
|
|
|
|
2023-01-27 12:06:16 -06:00
|
|
|
#include "tinyspline.h"
|
|
|
|
|
2022-12-26 20:57:45 -06:00
|
|
|
#include "script.h"
|
2023-02-02 17:52:15 -06:00
|
|
|
#include "ffi.h"
|
2022-12-26 20:57:45 -06:00
|
|
|
|
2022-12-20 08:16:26 -06:00
|
|
|
#include "log.h"
|
2022-08-17 00:01:51 -05:00
|
|
|
|
2021-11-30 21:29:18 -06:00
|
|
|
cpSpace *space = NULL;
|
|
|
|
float phys2d_gravity = -50.f;
|
|
|
|
|
2023-01-18 10:45:43 -06:00
|
|
|
float dbg_color[3] = {0.836f, 1.f, 0.45f};
|
|
|
|
float trigger_color[3] = {0.278f, 0.953f, 1.f};
|
|
|
|
float disabled_color[3] = {0.58f, 0.58f, 0.58f};
|
|
|
|
float dynamic_color[3] = {255/255, 70/255, 46/255};
|
|
|
|
float kinematic_color[3] = {255/255, 206/255,71/255};
|
|
|
|
float static_color[3] = {0.22f, 0.271f, 1.f};
|
|
|
|
|
|
|
|
void color2float(struct color color, float *fcolor)
|
|
|
|
{
|
|
|
|
fcolor[0] = (float)color.r/255;
|
|
|
|
fcolor[1] = (float)color.b/255;
|
|
|
|
fcolor[2] = (float)color.g/255;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct color float2color(float *fcolor)
|
|
|
|
{
|
|
|
|
struct color new;
|
|
|
|
new.r = fcolor[0]*255;
|
|
|
|
new.b = fcolor[1]*255;
|
|
|
|
new.g = fcolor[2]*255;
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
2023-02-02 17:52:15 -06:00
|
|
|
cpShape *phys2d_query_pos(cpVect pos)
|
|
|
|
{
|
|
|
|
cpShapeFilter filter;
|
|
|
|
filter.group = 0;
|
|
|
|
filter.mask = CP_ALL_CATEGORIES;
|
|
|
|
filter.categories = CP_ALL_CATEGORIES;
|
|
|
|
cpShape *find = cpSpacePointQueryNearest(space, pos, 0.f, filter, NULL);
|
|
|
|
|
|
|
|
return find;
|
|
|
|
}
|
|
|
|
|
2023-02-05 17:42:36 -06:00
|
|
|
int *qhits;
|
|
|
|
|
|
|
|
void querylist(cpShape *shape, cpContactPointSet *points, void *data)
|
|
|
|
{
|
2023-02-08 15:30:12 -06:00
|
|
|
int go = shape2gameobject(shape);
|
|
|
|
int in = 0;
|
|
|
|
for (int i = 0; i < arrlen(qhits); i++) {
|
|
|
|
if (qhits[i] == go) {
|
|
|
|
in = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!in) arrput(qhits, go);
|
2023-02-05 17:42:36 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void querylistbodies(cpBody *body, void *data)
|
|
|
|
{
|
|
|
|
cpBB *bbox = data;
|
|
|
|
if (cpBBContainsVect(*bbox, cpBodyGetPosition(body))) {
|
|
|
|
int go = body2id(body);
|
|
|
|
if (go < 0) return;
|
|
|
|
|
|
|
|
int in = 0;
|
|
|
|
for (int i = 0; i < arrlen(qhits); i++) {
|
|
|
|
if (qhits[i] == go) {
|
|
|
|
in = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!in) arrput(qhits, go);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int *phys2d_query_box(cpVect pos, cpVect wh)
|
|
|
|
{
|
2023-02-06 16:41:47 -06:00
|
|
|
cpShape *box = cpBoxShapeNew(NULL, wh.x, wh.y, 0.f);
|
|
|
|
cpTransform T = {0};
|
|
|
|
T.a = 1;
|
|
|
|
T.d = 1;
|
|
|
|
T.tx = pos.x;
|
|
|
|
T.ty = pos.y;
|
|
|
|
cpShapeUpdate(box, T);
|
2023-02-05 17:42:36 -06:00
|
|
|
|
2023-02-06 16:41:47 -06:00
|
|
|
cpBB bbox = cpShapeGetBB(box);
|
|
|
|
|
2023-02-05 17:42:36 -06:00
|
|
|
if (qhits) arrfree(qhits);
|
|
|
|
|
2023-02-06 16:41:47 -06:00
|
|
|
cpSpaceShapeQuery(space, box, querylist, NULL);
|
|
|
|
|
2023-02-05 17:42:36 -06:00
|
|
|
cpSpaceEachBody(space, querylistbodies, &bbox);
|
|
|
|
|
|
|
|
cpShapeFree(box);
|
|
|
|
|
|
|
|
return qhits;
|
|
|
|
}
|
|
|
|
|
2023-01-18 10:45:43 -06:00
|
|
|
int cpshape_enabled(cpShape *c)
|
2023-01-18 08:45:42 -06:00
|
|
|
{
|
2023-01-18 10:45:43 -06:00
|
|
|
cpShapeFilter filter = cpShapeGetFilter(c);
|
2023-01-18 08:45:42 -06:00
|
|
|
if (filter.categories == ~CP_ALL_CATEGORIES && filter.mask == ~CP_ALL_CATEGORIES)
|
2023-01-18 14:43:07 -06:00
|
|
|
return 0;
|
2023-01-18 08:45:42 -06:00
|
|
|
|
2023-01-18 14:43:07 -06:00
|
|
|
return 1;
|
2023-01-18 10:45:43 -06:00
|
|
|
}
|
2023-01-18 08:45:42 -06:00
|
|
|
|
2023-01-18 10:45:43 -06:00
|
|
|
float *shape_outline_color(cpShape *shape)
|
|
|
|
{
|
2023-01-18 08:45:42 -06:00
|
|
|
switch (cpBodyGetType(cpShapeGetBody(shape))) {
|
|
|
|
case CP_BODY_TYPE_DYNAMIC:
|
2023-01-18 10:45:43 -06:00
|
|
|
return dynamic_color;
|
2023-01-18 08:45:42 -06:00
|
|
|
|
|
|
|
case CP_BODY_TYPE_KINEMATIC:
|
2023-01-18 10:45:43 -06:00
|
|
|
return kinematic_color;
|
2023-01-18 08:45:42 -06:00
|
|
|
|
|
|
|
case CP_BODY_TYPE_STATIC:
|
2023-01-18 10:45:43 -06:00
|
|
|
return static_color;
|
2023-01-18 08:45:42 -06:00
|
|
|
}
|
|
|
|
|
2023-01-18 10:45:43 -06:00
|
|
|
return static_color;
|
2023-01-18 08:45:42 -06:00
|
|
|
}
|
|
|
|
|
2023-01-18 10:45:43 -06:00
|
|
|
float *shape_color(cpShape *shape)
|
2023-01-16 02:16:39 -06:00
|
|
|
{
|
2023-01-18 14:43:07 -06:00
|
|
|
if (!cpshape_enabled(shape)) return disabled_color;
|
2023-01-16 02:16:39 -06:00
|
|
|
|
2023-01-18 10:45:43 -06:00
|
|
|
if (cpShapeGetSensor(shape)) return trigger_color;
|
|
|
|
|
|
|
|
return dbg_color;
|
2023-01-16 02:16:39 -06:00
|
|
|
}
|
|
|
|
|
2021-11-30 21:29:18 -06:00
|
|
|
void phys2d_init()
|
|
|
|
{
|
|
|
|
space = cpSpaceNew();
|
2023-01-10 17:23:11 -06:00
|
|
|
cpVect grav = {0, phys2d_gravity};
|
|
|
|
phys2d_set_gravity(grav);
|
2021-11-30 21:29:18 -06:00
|
|
|
cpSpaceSetGravity(space, cpv(0, phys2d_gravity));
|
|
|
|
}
|
|
|
|
|
2023-01-10 17:23:11 -06:00
|
|
|
void phys2d_set_gravity(cpVect v) {
|
|
|
|
cpSpaceSetGravity(space, v);
|
2022-12-22 03:50:40 -06:00
|
|
|
}
|
|
|
|
|
2021-11-30 21:29:18 -06:00
|
|
|
void phys2d_update(float deltaT)
|
|
|
|
{
|
2022-02-04 11:36:24 -06:00
|
|
|
cpSpaceStep(space, deltaT);
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2023-01-13 08:05:36 -06:00
|
|
|
void init_phys2dshape(struct phys2d_shape *shape, int go, void *data)
|
2021-11-30 21:29:18 -06:00
|
|
|
{
|
|
|
|
shape->go = go;
|
2023-01-13 08:05:36 -06:00
|
|
|
shape->data = data;
|
2023-02-02 17:52:15 -06:00
|
|
|
go_shape_apply(id2go(go)->body, shape->shape, id2go(go));
|
2023-01-13 08:05:36 -06:00
|
|
|
cpShapeSetCollisionType(shape->shape, go);
|
|
|
|
cpShapeSetUserData(shape->shape, shape);
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2022-08-28 22:34:33 -05:00
|
|
|
void phys2d_shape_del(struct phys2d_shape *shape)
|
|
|
|
{
|
2023-02-15 17:54:05 -06:00
|
|
|
if (!shape->shape) return;
|
2022-08-28 22:34:33 -05:00
|
|
|
cpSpaceRemoveShape(space, shape->shape);
|
2023-02-15 17:54:05 -06:00
|
|
|
cpShapeFree(shape->shape);
|
2022-08-28 22:34:33 -05:00
|
|
|
}
|
|
|
|
|
2023-01-16 02:16:39 -06:00
|
|
|
/***************** CIRCLE2D *****************/
|
2023-01-12 17:41:54 -06:00
|
|
|
struct phys2d_circle *Make2DCircle(int go)
|
2021-11-30 21:29:18 -06:00
|
|
|
{
|
|
|
|
struct phys2d_circle *new = malloc(sizeof(struct phys2d_circle));
|
|
|
|
|
|
|
|
new->radius = 10.f;
|
2023-01-19 18:30:23 -06:00
|
|
|
new->offset = cpvzero;
|
2021-11-30 21:29:18 -06:00
|
|
|
|
2023-01-12 17:41:54 -06:00
|
|
|
new->shape.shape = cpSpaceAddShape(space, cpCircleShapeNew(id2go(go)->body, new->radius, cpvzero));
|
2023-01-13 08:05:36 -06:00
|
|
|
new->shape.debugdraw = phys2d_dbgdrawcircle;
|
|
|
|
init_phys2dshape(&new->shape, go, new);
|
2021-11-30 21:29:18 -06:00
|
|
|
|
2023-01-12 17:41:54 -06:00
|
|
|
return new;
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2022-08-28 22:34:33 -05:00
|
|
|
void phys2d_circledel(struct phys2d_circle *c)
|
|
|
|
{
|
|
|
|
phys2d_shape_del(&c->shape);
|
|
|
|
}
|
|
|
|
|
2023-02-20 11:10:03 -06:00
|
|
|
cpVect world2go(struct gameobject *go, cpVect worldpos)
|
|
|
|
{
|
2023-02-20 16:28:07 -06:00
|
|
|
cpTransform T = {0};
|
|
|
|
cpVect pos = cpBodyGetPosition(go->body);
|
|
|
|
worldpos.x -= pos.x;
|
|
|
|
worldpos.y -= pos.y;
|
|
|
|
// worldpos.x /= go->scale;
|
|
|
|
// worldpos.y /= go->scale;
|
|
|
|
float angle = cpBodyGetAngle(go->body);
|
|
|
|
T.a = go->flipx * cos(-angle) / go->scale;
|
|
|
|
T.b = sin(-angle) / go->scale;
|
|
|
|
T.c = -sin(-angle) / go->scale;
|
|
|
|
T.d = go->flipy * cos(-angle) / go->scale;
|
|
|
|
worldpos = cpTransformPoint(T,worldpos);
|
|
|
|
|
2023-02-20 11:10:03 -06:00
|
|
|
return worldpos;
|
|
|
|
}
|
|
|
|
|
|
|
|
cpVect go2world(struct gameobject *go, cpVect gopos)
|
|
|
|
{
|
|
|
|
cpVect pos = cpBodyGetPosition(go->body);
|
|
|
|
float angle = cpBodyGetAngle(go->body);
|
|
|
|
cpTransform T = {0};
|
|
|
|
T.a = go->scale * go->flipx * cos(angle);
|
2023-02-20 16:28:07 -06:00
|
|
|
T.b = sin(angle) * go->scale * go->flipx;
|
|
|
|
T.c = -sin(angle) * go->scale * go->flipy;
|
2023-02-20 11:10:03 -06:00
|
|
|
T.d = go->scale * go->flipy * cos(angle);
|
|
|
|
T.tx = pos.x;
|
|
|
|
T.ty = pos.y;
|
|
|
|
return cpTransformPoint(T, gopos);
|
|
|
|
}
|
|
|
|
|
2023-02-19 11:16:35 -06:00
|
|
|
cpVect gotransformpoint(struct gameobject *go, cpVect point)
|
|
|
|
{
|
|
|
|
point.x *= go->scale * go->flipx;
|
|
|
|
point.y *= go->scale * go->flipy;
|
|
|
|
return point;
|
|
|
|
}
|
2022-08-12 14:03:56 -05:00
|
|
|
|
2023-02-19 11:16:35 -06:00
|
|
|
cpVect bodytransformpoint(cpBody *body, cpVect offset)
|
|
|
|
{
|
|
|
|
cpVect pos = cpBodyGetPosition(body);
|
|
|
|
float d = sqrt(pow(offset.x, 2.f) + pow(offset.y, 2.f));
|
|
|
|
float a = atan2(offset.y, offset.x) + cpBodyGetAngle(body);
|
|
|
|
pos.x += d*cos(a);
|
|
|
|
pos.y += d*sin(a);
|
|
|
|
return pos;
|
2022-08-12 14:03:56 -05:00
|
|
|
}
|
|
|
|
|
2023-01-03 09:06:36 -06:00
|
|
|
void phys2d_dbgdrawcpcirc(cpCircleShape *c)
|
|
|
|
{
|
2023-02-19 11:16:35 -06:00
|
|
|
cpVect pos = bodytransformpoint(cpShapeGetBody(c), cpCircleShapeGetOffset(c));
|
2023-01-03 09:06:36 -06:00
|
|
|
float radius = cpCircleShapeGetRadius(c);
|
2023-02-19 11:16:35 -06:00
|
|
|
draw_circle(pos.x, pos.y, radius, 2, shape_color(c), 1);
|
2023-01-03 09:06:36 -06:00
|
|
|
}
|
|
|
|
|
2022-08-17 00:01:51 -05:00
|
|
|
void phys2d_dbgdrawcircle(struct phys2d_circle *circle)
|
|
|
|
{
|
2023-01-03 09:06:36 -06:00
|
|
|
phys2d_dbgdrawcpcirc((cpCircleShape *)circle->shape.shape);
|
2022-08-17 00:01:51 -05:00
|
|
|
}
|
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
void phys2d_applycircle(struct phys2d_circle *circle)
|
2022-08-28 22:34:33 -05:00
|
|
|
{
|
2023-01-25 21:32:58 -06:00
|
|
|
struct gameobject *go = id2go(circle->shape.go);
|
2022-08-28 22:34:33 -05:00
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
float radius = circle->radius * go->scale;
|
2023-02-19 11:16:35 -06:00
|
|
|
cpVect offset = gotransformpoint(go, circle->offset);
|
2022-08-12 14:03:56 -05:00
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
cpCircleShapeSetRadius(circle->shape.shape, radius);
|
|
|
|
cpCircleShapeSetOffset(circle->shape.shape, offset);
|
2022-08-12 14:03:56 -05:00
|
|
|
}
|
|
|
|
|
2023-01-12 17:41:54 -06:00
|
|
|
/************* BOX2D ************/
|
|
|
|
|
|
|
|
struct phys2d_box *Make2DBox(int go)
|
2021-11-30 21:29:18 -06:00
|
|
|
{
|
|
|
|
struct phys2d_box *new = malloc(sizeof(struct phys2d_box));
|
|
|
|
|
|
|
|
new->w = 50.f;
|
|
|
|
new->h = 50.f;
|
|
|
|
new->r = 0.f;
|
|
|
|
new->offset[0] = 0.f;
|
|
|
|
new->offset[1] = 0.f;
|
2023-02-15 17:54:05 -06:00
|
|
|
new->shape.go = go;
|
2023-01-12 17:41:54 -06:00
|
|
|
phys2d_applybox(new);
|
2023-02-15 17:54:05 -06:00
|
|
|
new->shape.debugdraw = phys2d_dbgdrawbox;
|
2021-11-30 21:29:18 -06:00
|
|
|
|
2023-01-12 17:41:54 -06:00
|
|
|
return new;
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2023-02-19 11:16:35 -06:00
|
|
|
cpTransform go2transform(struct gameobject *go, cpVect offset, float angle)
|
2022-08-28 22:34:33 -05:00
|
|
|
{
|
2023-02-19 11:16:35 -06:00
|
|
|
cpTransform T = {0};
|
|
|
|
T.a = cos(angle) * go->scale * go->flipx;
|
|
|
|
T.b = -sin(angle) * go->scale * go->flipx;
|
|
|
|
T.c = sin(angle) * go->scale * go->flipy;
|
|
|
|
T.d = cos(angle) * go->scale * go->flipy;
|
|
|
|
T.tx = offset.x * go->scale;
|
|
|
|
T.ty = offset.y * go->scale;
|
|
|
|
return T;
|
2022-08-28 22:34:33 -05:00
|
|
|
}
|
|
|
|
|
2023-02-19 11:16:35 -06:00
|
|
|
void phys2d_boxdel(struct phys2d_box *box)
|
2022-08-12 14:03:56 -05:00
|
|
|
{
|
2023-02-19 11:16:35 -06:00
|
|
|
phys2d_shape_del(&box->shape);
|
2022-08-12 14:03:56 -05:00
|
|
|
}
|
|
|
|
|
2023-01-19 10:44:29 -06:00
|
|
|
void phys2d_applybox(struct phys2d_box *box)
|
|
|
|
{
|
2023-02-15 17:54:05 -06:00
|
|
|
phys2d_boxdel(box);
|
|
|
|
struct gameobject *go = id2go(box->shape.go);
|
2023-02-19 11:16:35 -06:00
|
|
|
cpVect off;
|
|
|
|
off.x = box->offset[0];
|
|
|
|
off.y = box->offset[1];
|
|
|
|
cpTransform T = go2transform(id2go(box->shape.go), off, box->rotation);
|
2023-01-19 10:44:29 -06:00
|
|
|
float hh = box->h / 2.f;
|
|
|
|
float hw = box->w / 2.f;
|
2023-01-25 21:32:58 -06:00
|
|
|
cpVect verts[4] = { { -hw, -hh }, { hw, -hh }, { hw, hh }, { -hw, hh } };
|
2023-02-15 17:54:05 -06:00
|
|
|
box->shape.shape = cpSpaceAddShape(space, cpPolyShapeNew(go->body, 4, verts, T, box->r));
|
|
|
|
init_phys2dshape(&box->shape, box->shape.go, box);
|
2023-01-19 10:44:29 -06:00
|
|
|
}
|
2023-02-19 11:16:35 -06:00
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
void phys2d_dbgdrawbox(struct phys2d_box *box)
|
|
|
|
{
|
|
|
|
int n = cpPolyShapeGetCount(box->shape.shape);
|
|
|
|
float points[n * 2];
|
2023-02-19 11:16:35 -06:00
|
|
|
|
|
|
|
for (int i = 0; i < n; i++)
|
|
|
|
points[i] = bodytransformpoint(cpShapeGetBody(box->shape.shape), cpPolyShapeGetVert(box->shape.shape, i));
|
2023-01-25 21:32:58 -06:00
|
|
|
|
|
|
|
draw_poly(points, n, shape_color(box->shape.shape));
|
|
|
|
}
|
2023-01-12 17:41:54 -06:00
|
|
|
/************** POLYGON ************/
|
2022-08-12 14:03:56 -05:00
|
|
|
|
2023-01-12 17:41:54 -06:00
|
|
|
struct phys2d_poly *Make2DPoly(int go)
|
2021-11-30 21:29:18 -06:00
|
|
|
{
|
|
|
|
struct phys2d_poly *new = malloc(sizeof(struct phys2d_poly));
|
|
|
|
|
2023-02-17 22:32:23 -06:00
|
|
|
new->points = NULL;
|
2023-01-25 21:32:58 -06:00
|
|
|
arrsetlen(new->points, 0);
|
2021-11-30 21:29:18 -06:00
|
|
|
new->radius = 0.f;
|
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
new->shape.shape = cpSpaceAddShape(space, cpPolyShapeNewRaw(id2go(go)->body, 0, new->points, new->radius));
|
2023-01-13 08:05:36 -06:00
|
|
|
new->shape.debugdraw = phys2d_dbgdrawpoly;
|
2023-01-25 21:32:58 -06:00
|
|
|
init_phys2dshape(&new->shape, go, new);
|
2023-01-12 17:41:54 -06:00
|
|
|
return new;
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2022-08-28 22:34:33 -05:00
|
|
|
void phys2d_polydel(struct phys2d_poly *poly)
|
|
|
|
{
|
2023-01-25 21:32:58 -06:00
|
|
|
arrfree(poly->points);
|
2022-08-28 22:34:33 -05:00
|
|
|
phys2d_shape_del(&poly->shape);
|
|
|
|
}
|
|
|
|
|
2021-11-30 21:29:18 -06:00
|
|
|
void phys2d_polyaddvert(struct phys2d_poly *poly)
|
|
|
|
{
|
2023-01-25 21:32:58 -06:00
|
|
|
arrput(poly->points, cpvzero);
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
void phys2d_poly_setverts(struct phys2d_poly *poly, cpVect *verts)
|
|
|
|
{
|
2023-02-17 22:32:23 -06:00
|
|
|
if (!verts) return;
|
2023-01-25 21:32:58 -06:00
|
|
|
arrfree(poly->points);
|
|
|
|
poly->points = verts;
|
|
|
|
phys2d_applypoly(poly);
|
|
|
|
}
|
2022-08-12 14:03:56 -05:00
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
void phys2d_applypoly(struct phys2d_poly *poly)
|
|
|
|
{
|
|
|
|
if (arrlen(poly->points) <= 0) return;
|
2023-02-19 11:16:35 -06:00
|
|
|
struct gameobject *go = id2go(poly->shape.go);
|
|
|
|
|
|
|
|
cpTransform T = go2transform(go, cpvzero, 0);
|
2022-08-12 14:03:56 -05:00
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
cpPolyShapeSetVerts(poly->shape.shape, arrlen(poly->points), poly->points, T);
|
|
|
|
cpPolyShapeSetRadius(poly->shape.shape, poly->radius);
|
2023-02-19 11:16:35 -06:00
|
|
|
cpSpaceReindexShapesForBody(space, cpShapeGetBody(poly->shape.shape));
|
2022-08-12 14:03:56 -05:00
|
|
|
}
|
2023-01-25 21:32:58 -06:00
|
|
|
void phys2d_dbgdrawpoly(struct phys2d_poly *poly)
|
|
|
|
{
|
|
|
|
float *color = shape_color(poly->shape.shape);
|
|
|
|
int n = arrlen(poly->points);
|
2022-08-12 14:03:56 -05:00
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
if (arrlen(poly->points) >= 3) {
|
|
|
|
int n = cpPolyShapeGetCount(poly->shape.shape);
|
|
|
|
float points[n * 2];
|
2023-01-12 17:41:54 -06:00
|
|
|
|
2023-02-19 11:16:35 -06:00
|
|
|
for (int i = 0; i < n; i++)
|
|
|
|
points[i*2] = bodytransformpoint(cpShapeGetBody(poly->shape.shape), cpPolyShapeGetVert(poly->shape.shape, i));
|
2023-01-25 21:32:58 -06:00
|
|
|
|
|
|
|
draw_poly(points, n, color);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2023-01-12 17:41:54 -06:00
|
|
|
/****************** EDGE 2D**************/
|
|
|
|
|
|
|
|
struct phys2d_edge *Make2DEdge(int go)
|
2021-11-30 21:29:18 -06:00
|
|
|
{
|
|
|
|
struct phys2d_edge *new = malloc(sizeof(struct phys2d_edge));
|
2023-01-25 21:32:58 -06:00
|
|
|
new->points = NULL;
|
|
|
|
arrsetlen(new->points, 0);
|
2021-11-30 21:29:18 -06:00
|
|
|
new->thickness = 0.f;
|
2023-01-25 21:32:58 -06:00
|
|
|
new->shapes = NULL;
|
|
|
|
arrsetlen(new->shapes, 0);
|
2023-01-12 17:41:54 -06:00
|
|
|
new->shape.go = go;
|
2023-01-25 21:32:58 -06:00
|
|
|
new->shape.data = new;
|
|
|
|
new->shape.debugdraw = phys2d_dbgdrawedge;
|
2023-01-12 17:41:54 -06:00
|
|
|
phys2d_applyedge(new);
|
2021-11-30 21:29:18 -06:00
|
|
|
|
2023-01-12 17:41:54 -06:00
|
|
|
return new;
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2022-08-28 22:34:33 -05:00
|
|
|
void phys2d_edgedel(struct phys2d_edge *edge)
|
|
|
|
{
|
|
|
|
phys2d_shape_del(&edge->shape);
|
|
|
|
}
|
|
|
|
|
2021-11-30 21:29:18 -06:00
|
|
|
void phys2d_edgeaddvert(struct phys2d_edge *edge)
|
|
|
|
{
|
2023-01-25 21:32:58 -06:00
|
|
|
arrput(edge->points, cpvzero);
|
|
|
|
if (arrlen(edge->points) > 1)
|
|
|
|
arrput(edge->shapes, cpSpaceAddShape(space, cpSegmentShapeNew(id2go(edge->shape.go)->body, cpvzero, cpvzero, edge->thickness)));
|
2022-08-12 14:03:56 -05:00
|
|
|
|
|
|
|
phys2d_applyedge(edge);
|
|
|
|
}
|
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
void phys2d_edge_rmvert(struct phys2d_edge *edge, int index)
|
2021-11-30 21:29:18 -06:00
|
|
|
{
|
2023-01-25 21:32:58 -06:00
|
|
|
assert(arrlen(edge->points) > index && index >= 0);
|
2023-01-12 17:41:54 -06:00
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
arrdel(edge->points, index);
|
2023-02-08 15:30:12 -06:00
|
|
|
|
|
|
|
if (arrlen(edge->points) == 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
if (index == 0) {
|
|
|
|
cpSpaceRemoveShape(space, edge->shapes[index]);
|
|
|
|
arrdel(edge->shapes, index);
|
|
|
|
phys2d_applyedge(edge);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index != arrlen(edge->points)) {
|
|
|
|
cpSegmentShapeSetEndpoints(edge->shapes[index-1], edge->points[index-1], edge->points[index]);
|
|
|
|
}
|
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
cpSpaceRemoveShape(space, edge->shapes[index-1]);
|
|
|
|
arrdel(edge->shapes, index-1);
|
2021-11-30 21:29:18 -06:00
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
phys2d_applyedge(edge);
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2023-02-02 17:52:15 -06:00
|
|
|
void phys2d_edge_setvert(struct phys2d_edge *edge, int index, cpVect val)
|
2021-11-30 21:29:18 -06:00
|
|
|
{
|
2023-01-25 21:32:58 -06:00
|
|
|
assert(arrlen(edge->points) > index && index >= 0);
|
|
|
|
edge->points[index] = val;
|
2021-11-30 21:29:18 -06:00
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
phys2d_applyedge(edge);
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2023-02-08 15:30:12 -06:00
|
|
|
void phys2d_edge_clearverts(struct phys2d_edge *edge)
|
|
|
|
{
|
|
|
|
for (int i = arrlen(edge->points)-1; i>=0; i--) {
|
|
|
|
phys2d_edge_rmvert(edge, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void phys2d_edge_addverts(struct phys2d_edge *edge, cpVect *verts)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < arrlen(verts); i++) {
|
|
|
|
phys2d_edgeaddvert(edge);
|
|
|
|
phys2d_edge_setvert(edge, i, verts[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-30 21:29:18 -06:00
|
|
|
void phys2d_applyedge(struct phys2d_edge *edge)
|
|
|
|
{
|
2023-02-19 11:16:35 -06:00
|
|
|
struct gameobject *go = id2go(edge->shape.go);
|
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
for (int i = 0; i < arrlen(edge->shapes); i++) {
|
2023-02-19 11:16:35 -06:00
|
|
|
cpVect a = gotransformpoint(go, edge->points[i]);
|
|
|
|
cpVect b = gotransformpoint(go, edge->points[i+1]);
|
2021-11-30 21:29:18 -06:00
|
|
|
cpSegmentShapeSetEndpoints(edge->shapes[i], a, b);
|
|
|
|
cpSegmentShapeSetRadius(edge->shapes[i], edge->thickness);
|
2023-02-19 11:16:35 -06:00
|
|
|
go_shape_apply(NULL, edge->shapes[i], go);
|
2023-01-25 21:32:58 -06:00
|
|
|
cpShapeSetUserData(edge->shapes[i], &edge->shape);
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
cpSpaceReindexShapesForBody(space, id2go(edge->shape.go)->body);
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
void phys2d_dbgdrawedge(struct phys2d_edge *edge)
|
2021-11-30 21:29:18 -06:00
|
|
|
{
|
2023-01-25 21:32:58 -06:00
|
|
|
edge->draws++;
|
|
|
|
if (edge->draws > 1) {
|
|
|
|
if (edge->draws >= arrlen(edge->shapes))
|
|
|
|
edge->draws = 0;
|
2021-11-30 21:29:18 -06:00
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
return;
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
if (arrlen(edge->shapes) < 1) return;
|
2021-11-30 21:29:18 -06:00
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
cpVect drawpoints[arrlen(edge->points)];
|
2023-02-19 11:16:35 -06:00
|
|
|
struct gameobject *go = id2go(edge->shape.go);
|
2021-11-30 21:29:18 -06:00
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
for (int i = 0; i < arrlen(edge->points); i++) {
|
2023-02-19 11:16:35 -06:00
|
|
|
drawpoints[i] = gotransformpoint(go, edge->points[i]);
|
|
|
|
drawpoints[i] = bodytransformpoint(cpShapeGetBody(edge->shapes[0]), drawpoints[i]);
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2023-02-17 22:32:23 -06:00
|
|
|
draw_edge(drawpoints, arrlen(edge->points), shape_color(edge->shapes[0]), edge->thickness*2);
|
2023-01-25 21:32:58 -06:00
|
|
|
draw_points(drawpoints, arrlen(edge->points), 2, kinematic_color);
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2022-12-20 08:16:26 -06:00
|
|
|
|
2023-01-25 21:32:58 -06:00
|
|
|
/************ COLLIDER ****************/
|
2023-01-17 15:09:14 -06:00
|
|
|
void shape_enabled(struct phys2d_shape *shape, int enabled)
|
2023-01-16 17:18:09 -06:00
|
|
|
{
|
2023-01-17 15:09:14 -06:00
|
|
|
if (enabled)
|
2023-01-18 08:45:42 -06:00
|
|
|
cpShapeSetFilter(shape->shape, CP_SHAPE_FILTER_ALL);
|
2023-01-17 15:09:14 -06:00
|
|
|
else
|
2023-01-18 08:45:42 -06:00
|
|
|
cpShapeSetFilter(shape->shape, CP_SHAPE_FILTER_NONE);
|
2023-01-16 17:18:09 -06:00
|
|
|
}
|
|
|
|
|
2023-01-18 10:45:43 -06:00
|
|
|
int shape_is_enabled(struct phys2d_shape *shape)
|
|
|
|
{
|
|
|
|
if (cpshape_enabled(shape->shape))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-01-17 15:09:14 -06:00
|
|
|
void shape_set_sensor(struct phys2d_shape *shape, int sensor)
|
2023-01-17 13:04:08 -06:00
|
|
|
{
|
2023-02-17 13:15:56 -06:00
|
|
|
if (!shape->shape) {
|
|
|
|
struct phys2d_edge *edge = shape->data;
|
|
|
|
|
|
|
|
for (int i = 0; i < arrlen(edge->shapes); i++) {
|
|
|
|
cpShapeSetSensor(edge->shapes[i], sensor);
|
|
|
|
YughInfo("Setting shape %d sensor to %d", i, sensor);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
cpShapeSetSensor(shape->shape, sensor);
|
2023-01-17 13:04:08 -06:00
|
|
|
}
|
|
|
|
|
2023-01-18 10:45:43 -06:00
|
|
|
int shape_get_sensor(struct phys2d_shape *shape)
|
|
|
|
{
|
2023-02-17 13:15:56 -06:00
|
|
|
if (!shape->shape) {
|
|
|
|
return cpShapeGetSensor(((struct phys2d_edge *)(shape->data))->shapes[0]);
|
|
|
|
}
|
2023-01-18 10:45:43 -06:00
|
|
|
return cpShapeGetSensor(shape->shape);
|
|
|
|
}
|
|
|
|
|
2022-12-21 19:24:59 -06:00
|
|
|
void phys2d_reindex_body(cpBody *body) {
|
|
|
|
cpSpaceReindexShapesForBody(space, body);
|
|
|
|
}
|
|
|
|
|
2023-01-18 10:45:43 -06:00
|
|
|
|
2023-01-11 16:57:34 -06:00
|
|
|
void register_collide(void *sym) {
|
2022-12-21 19:24:59 -06:00
|
|
|
|
2023-01-11 16:57:34 -06:00
|
|
|
}
|
|
|
|
|
2023-02-17 01:16:52 -06:00
|
|
|
void duk_call_phys_cb(cpArbiter *arb, struct callee c, int hit)
|
|
|
|
{
|
|
|
|
duk_push_heapptr(duk, c.fn);
|
|
|
|
duk_push_heapptr(duk, c.obj);
|
2023-01-11 16:57:34 -06:00
|
|
|
|
|
|
|
int obj = duk_push_object(duk);
|
2022-12-28 16:50:54 -06:00
|
|
|
|
2023-01-11 16:57:34 -06:00
|
|
|
vect2duk(cpArbiterGetNormal(arb));
|
|
|
|
duk_put_prop_literal(duk, obj, "normal");
|
|
|
|
|
2023-02-17 01:16:52 -06:00
|
|
|
duk_push_int(duk, hit);
|
2023-01-11 16:57:34 -06:00
|
|
|
duk_put_prop_literal(duk, obj, "hit");
|
|
|
|
|
|
|
|
duk_call_method(duk, 1);
|
|
|
|
duk_pop(duk);
|
2023-02-17 01:16:52 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static cpBool script_phys_cb_begin(cpArbiter *arb, cpSpace *space, void *data) {
|
|
|
|
|
|
|
|
cpBody *body1;
|
|
|
|
cpBody *body2;
|
|
|
|
cpArbiterGetBodies(arb, &body1, &body2);
|
|
|
|
|
|
|
|
cpShape *shape1;
|
|
|
|
cpShape *shape2;
|
|
|
|
cpArbiterGetShapes(arb, &shape1, &shape2);
|
|
|
|
|
|
|
|
int g1 = cpBodyGetUserData(body1);
|
|
|
|
int g2 = cpBodyGetUserData(body2);
|
|
|
|
struct gameobject *go = id2go(g1);
|
|
|
|
|
|
|
|
for (int i = 0; i < arrlen(go->shape_cbs); i++) {
|
|
|
|
if (go->shape_cbs[i].shape != shape1) continue;
|
|
|
|
duk_call_phys_cb(arb, go->shape_cbs[i].cbs.begin, g2);
|
|
|
|
}
|
|
|
|
|
|
|
|
duk_call_phys_cb(arb, go->cbs.begin, g2);
|
2022-12-21 19:24:59 -06:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-01-12 17:41:54 -06:00
|
|
|
void phys2d_add_handler_type(int cmd, int go, struct callee c) {
|
2022-12-21 19:24:59 -06:00
|
|
|
cpCollisionHandler *handler = cpSpaceAddWildcardHandler(space, go);
|
|
|
|
|
2023-01-13 08:05:36 -06:00
|
|
|
handler->userData = go;
|
2022-12-21 19:24:59 -06:00
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case 0:
|
2023-01-11 16:57:34 -06:00
|
|
|
handler->beginFunc = script_phys_cb_begin;
|
2023-01-12 17:41:54 -06:00
|
|
|
id2go(go)->cbs.begin = c;
|
2022-12-21 19:24:59 -06:00
|
|
|
break;
|
2022-12-20 08:16:26 -06:00
|
|
|
|
2022-12-21 19:24:59 -06:00
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
2023-01-10 14:02:24 -06:00
|
|
|
//handler->separateFunc = s7_phys_cb_separate;
|
|
|
|
//go->cbs->separate = cb;
|
2022-12-21 19:24:59 -06:00
|
|
|
break;
|
|
|
|
}
|
2023-01-13 08:05:36 -06:00
|
|
|
|
2023-02-02 17:52:15 -06:00
|
|
|
}
|