Fixed debug circle drawing; add collision detection

This commit is contained in:
John Alanbrook 2022-12-22 01:24:59 +00:00
parent 2bcee44677
commit d81f2f373c
12 changed files with 160 additions and 73 deletions

View file

@ -13,7 +13,6 @@
#include "log.h" #include "log.h"
cpBody *ballBody = NULL;
cpSpace *space = NULL; cpSpace *space = NULL;
float phys2d_gravity = -50.f; float phys2d_gravity = -50.f;
@ -42,6 +41,8 @@ void phys2d_shape_apply(struct phys2d_shape *shape)
void init_phys2dshape(struct phys2d_shape *shape, struct gameobject *go) void init_phys2dshape(struct phys2d_shape *shape, struct gameobject *go)
{ {
shape->go = go; shape->go = go;
cpShapeSetCollisionType(shape->shape, go);
YughInfo("Added shape type %d", go);
phys2d_shape_apply(shape); phys2d_shape_apply(shape);
} }
@ -140,9 +141,7 @@ struct phys2d_box *Make2DBox(struct gameobject *go)
void phys2d_boxinit(struct phys2d_box *box, struct gameobject *go) void phys2d_boxinit(struct phys2d_box *box, struct gameobject *go)
{ {
box->shape.shape = box->shape.shape = cpSpaceAddShape(space, cpBoxShapeNew(go->body, box->w, box->h, box->r));
cpSpaceAddShape(space,
cpBoxShapeNew(go->body, box->w, box->h, box->r));
init_phys2dshape(&box->shape, go); init_phys2dshape(&box->shape, go);
phys2d_applybox(box); phys2d_applybox(box);
} }
@ -179,9 +178,7 @@ void phys2d_polyinit(struct phys2d_poly *poly, struct gameobject *go)
{ {
cpTransform T = { 0 }; cpTransform T = { 0 };
poly->shape.shape = poly->shape.shape =
cpSpaceAddShape(space, cpSpaceAddShape(space, cpPolyShapeNew(go->body, 0, NULL, T, poly->radius));
cpPolyShapeNew(go->body, 0, NULL, T,
poly->radius));
init_phys2dshape(&poly->shape, go); init_phys2dshape(&poly->shape, go);
phys2d_applypoly(poly); phys2d_applypoly(poly);
} }
@ -231,14 +228,10 @@ struct phys2d_edge *Make2DEdge(struct gameobject *go)
void phys2d_edgeinit(struct phys2d_edge *edge, struct gameobject *go) void phys2d_edgeinit(struct phys2d_edge *edge, struct gameobject *go)
{ {
edge->shapes[0] = edge->shapes[0] =
cpSpaceAddShape(space, cpSpaceAddShape(space, cpSegmentShapeNew(go->body, cpvzero, cpvzero, edge->thickness));
cpSegmentShapeNew(go->body, cpvzero, cpvzero,
edge->thickness));
edge->shape.go = go; edge->shape.go = go;
phys2d_edgeshapeapply(&edge->shape, edge->shapes[0]); phys2d_edgeshapeapply(&edge->shape, edge->shapes[0]);
phys2d_applyedge(edge); phys2d_applyedge(edge);
} }
@ -283,11 +276,8 @@ void edge_gui(struct phys2d_edge *edge)
{ {
if (nk_button_label(ctx, "Add Edge Vertex")) phys2d_edgeaddvert(edge); if (nk_button_label(ctx, "Add Edge Vertex")) phys2d_edgeaddvert(edge);
for (int i = 0; i < edge->n; i++) { for (int i = 0; i < edge->n; i++)
//ImGui::PushID(i);
nk_property_float2(ctx, "E", 0.f, &edge->points[i*2], 1.f, 0.01f, 0.01f); nk_property_float2(ctx, "E", 0.f, &edge->points[i*2], 1.f, 0.01f, 0.01f);
//ImGui::PopID();
}
nk_property_float(ctx, "Thickness", 0.01f, &edge->thickness, 1.f, 0.01f, 0.01f); nk_property_float(ctx, "Thickness", 0.01f, &edge->thickness, 1.f, 0.01f, 0.01f);
@ -304,9 +294,7 @@ void phys2d_applycircle(struct phys2d_circle *circle)
cpCircleShapeSetRadius(circle->shape.shape, radius); cpCircleShapeSetRadius(circle->shape.shape, radius);
cpCircleShapeSetOffset(circle->shape.shape, offset); cpCircleShapeSetOffset(circle->shape.shape, offset);
cpBodySetMoment(circle->shape.go->body, cpBodySetMoment(circle->shape.go->body, cpMomentForCircle(circle->shape.go->mass, 0, radius, offset));
cpMomentForCircle(circle->shape.go->mass, 0, radius,
offset));
} }
void phys2d_applyseg(struct phys2d_segment *seg) void phys2d_applyseg(struct phys2d_segment *seg)
@ -461,18 +449,67 @@ void phys2d_dbgdrawedge(struct phys2d_edge *edge)
} }
} }
s7_pointer *cbs; void phys2d_reindex_body(cpBody *body) {
cpSpaceReindexShapesForBody(space, body);
static cpBool s7_phys_cb(cpArbiter *arb, cpSpace *space, void *data) {
s7_pointer *cb = data;
script_call_sym(*cb);
} }
void phys2d_add_begin_handler(s7_pointer cb) {
arrput(cbs, cb);
cpCollisionHandler *handler = cpSpaceAddDefaultCollisionHandler(space);
handler->userData = &arrlast(cbs);
handler->beginFunc = s7_phys_cb;
YughInfo("Added a phys collider CB."); static cpBool s7_phys_cb_begin(cpArbiter *arb, cpSpace *space, void *data) {
struct gameobject *go = data;
script_call_sym(go->cbs->begin);
YughInfo("Gameobject %p began collision.", data);
cpBody *body1;
cpBody *body2;
cpArbiterGetBodies(arb, &body1, &body2);
cpShape *shape1;
cpShape *shape2;
cpArbiterGetShapes(arb, &shape1, &shape2);
YughInfo("Body %p began collision with body %p.", body1, body2);
YughInfo("Shape %p began collision with shape %p.", shape1, shape2);
return 1;
}
static cpBool s7_phys_cb_presolve(cpArbiter *arb, cpSpace *space, void *data) {
}
static void s7_phys_cb_postsolve(cpArbiter *arb, cpSpace *space, void *data) {
}
static void s7_phys_cb_separate(cpArbiter *Arb, cpSpace *space, void *data) {
struct gameobject *go = data;
script_call_sym(go->cbs->separate);
}
void phys2d_add_handler_type(int cmd, struct gameobject *go, s7_pointer cb) {
cpCollisionHandler *handler = cpSpaceAddWildcardHandler(space, go);
if (!go->cbs)
go->cbs = malloc(sizeof(*go->cbs));
handler->userData = go;
YughInfo("Making phys handler %d for type %d", cmd, go);
switch (cmd) {
case 0:
handler->beginFunc = s7_phys_cb_begin;
go->cbs->begin = cb;
break;
case 1:
break;
case 2:
break;
case 3:
handler->separateFunc = s7_phys_cb_separate;
go->cbs->separate = cb;
break;
}
} }

View file

@ -11,6 +11,11 @@ extern float phys2d_gravity;
extern int physOn; extern int physOn;
extern cpSpace *space; extern cpSpace *space;
struct phys_cbs {
s7_pointer begin;
s7_pointer separate;
};
struct phys2d_shape { struct phys2d_shape {
cpShape *shape; cpShape *shape;
struct gameobject *go; struct gameobject *go;
@ -95,8 +100,10 @@ void phys2d_init();
void phys2d_update(float deltaT); void phys2d_update(float deltaT);
void phys2d_apply(); void phys2d_apply();
void phys2d_add_begin_handler(s7_pointer cb); void phys2d_add_handler_type(int cmd, struct gameobject *go, s7_pointer cb);
void shape_gui(struct phys2d_shape *shape); void shape_gui(struct phys2d_shape *shape);
void phys2d_reindex_body(cpBody *body);
#endif #endif

View file

@ -3,6 +3,7 @@
#include "openglrender.h" #include "openglrender.h"
#include "shader.h" #include "shader.h"
#include "log.h"
static uint32_t circleVBO; static uint32_t circleVBO;
static uint32_t circleVAO; static uint32_t circleVAO;
@ -68,10 +69,10 @@ void draw_circle(int x, int y, float radius, int pixels)
shader_use(circleShader); shader_use(circleShader);
float verts[] = { float verts[] = {
x - radius, y - radius, x - radius, y - radius, -1, -1,
x + radius, y - radius, x + radius, y - radius, 1, -1,
x - radius, y + radius, x - radius, y + radius, -1, 1,
x + radius, y + radius, x + radius, y + radius, 1, 1
}; };
glBindBuffer(GL_ARRAY_BUFFER, circleVBO); glBindBuffer(GL_ARRAY_BUFFER, circleVBO);
@ -82,7 +83,7 @@ void draw_circle(int x, int y, float radius, int pixels)
glBindVertexArray(circleVAO); glBindVertexArray(circleVAO);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
} }

View file

@ -57,7 +57,8 @@ struct gameobject *MakeGameobject()
gameobject_setpickcolor(&go); gameobject_setpickcolor(&go);
strncpy(go.editor.mname, "New object", MAXNAME); strncpy(go.editor.mname, "New object", MAXNAME);
go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f)); go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f));
arrput(gameobjects, go); arrput(gameobjects, go);
@ -151,13 +152,6 @@ void gameobject_init(struct gameobject *go, FILE * fprefab)
int n; int n;
for (int i = 0; i < comp_n; i++) { for (int i = 0; i < comp_n; i++) {
/*
fread(&n, sizeof(int), 1, fprefab);
go->components[i] = components[n];
struct component *newc = &go->components[i];
newc->go = go;
newc->data = calloc(1, newc->datasize);
*/
fread(&n, sizeof(int), 1, fprefab); fread(&n, sizeof(int), 1, fprefab);
arrput(go->components, components[n]); arrput(go->components, components[n]);
struct component *newc = &arrlast(go->components); struct component *newc = &arrlast(go->components);
@ -217,18 +211,14 @@ void toggleprefab(struct gameobject *go)
} }
} }
void gameobject_update(struct gameobject *go)
{
if (go->script)
script_run(go->script);
}
void gameobject_move(struct gameobject *go, float xs, float ys) void gameobject_move(struct gameobject *go, float xs, float ys)
{ {
cpVect p = cpBodyGetPosition(go->body); cpVect p = cpBodyGetPosition(go->body);
p.x += xs * deltaT; p.x += xs * deltaT;
p.y += ys * deltaT; p.y += ys * deltaT;
cpBodySetPosition(go->body, p); cpBodySetPosition(go->body, p);
phys2d_reindex_body(go->body);
} }
void gameobject_rotate(struct gameobject *go, float as) void gameobject_rotate(struct gameobject *go, float as)
@ -236,10 +226,14 @@ void gameobject_rotate(struct gameobject *go, float as)
cpFloat a = cpBodyGetAngle(go->body); cpFloat a = cpBodyGetAngle(go->body);
a += as * deltaT; a += as * deltaT;
cpBodySetAngle(go->body, a); cpBodySetAngle(go->body, a);
phys2d_reindex_body(go->body);
} }
void gameobject_setangle(struct gameobject *go, float angle) { void gameobject_setangle(struct gameobject *go, float angle) {
cpBodySetAngle(go->body, angle); cpBodySetAngle(go->body, angle);
phys2d_reindex_body(go->body);
} }
void gameobject_setpos(struct gameobject *go, float x, float y) { void gameobject_setpos(struct gameobject *go, float x, float y) {
@ -248,14 +242,10 @@ void gameobject_setpos(struct gameobject *go, float x, float y) {
p.x = x; p.x = x;
p.y = y; p.y = y;
cpBodySetPosition(go->body, p); cpBodySetPosition(go->body, p);
}
void update_gameobjects() { phys2d_reindex_body(go->body);
for (int i = 0; i < arrlen(gameobjects); i++)
gameobject_update(&gameobjects[i]);
} }
void object_gui(struct gameobject *go) void object_gui(struct gameobject *go)
{ {
float temp_pos[2]; float temp_pos[2];
@ -323,3 +313,13 @@ void object_gui(struct gameobject *go)
gameobject_delcomponent(go, n); gameobject_delcomponent(go, n);
} }
void gameobject_draw_debugs() {
for (int i = 0; i < arrlen(gameobjects); i++) {
for (int j = 0; j < arrlen(gameobjects[i].components); j++) {
struct component *c = &gameobjects[i].components[j];
if (c->draw_debug) c->draw_debug(c->data);
}
}
}

View file

@ -7,6 +7,7 @@
#include "config.h" #include "config.h"
#include <stdbool.h> #include <stdbool.h>
#include <chipmunk/chipmunk.h> #include <chipmunk/chipmunk.h>
#include "2dphysics.h"
struct shader; struct shader;
struct sprite; struct sprite;
@ -23,6 +24,10 @@ struct editor {
char rootPrefabName[MAXNAME]; char rootPrefabName[MAXNAME];
}; };
struct go_temp {
struct phys_cbs phys_cbs;
};
struct gameobject { struct gameobject {
struct mTransform transform; struct mTransform transform;
struct editor editor; struct editor editor;
@ -33,7 +38,7 @@ struct gameobject {
float f; /* friction */ float f; /* friction */
float e; /* elasticity */ float e; /* elasticity */
struct component *components; struct component *components;
char *script; struct phys_cbs *cbs;
}; };
extern struct gameobject *gameobjects; extern struct gameobject *gameobjects;
@ -62,14 +67,13 @@ void gameobject_revertprefab(struct gameobject *go);
void gameobject_init(struct gameobject *go, FILE * fprefab); void gameobject_init(struct gameobject *go, FILE * fprefab);
void gameobject_update(struct gameobject *go);
void update_gameobjects();
void gameobject_move(struct gameobject *go, float xs, float ys); void gameobject_move(struct gameobject *go, float xs, float ys);
void gameobject_rotate(struct gameobject *go, float as); void gameobject_rotate(struct gameobject *go, float as);
void gameobject_setangle(struct gameobject *go, float angle); void gameobject_setangle(struct gameobject *go, float angle);
void gameobject_setpos(struct gameobject *go, float x, float y); void gameobject_setpos(struct gameobject *go, float x, float y);
void gameobject_draw_debugs();
void object_gui(struct gameobject *go); void object_gui(struct gameobject *go);
#endif #endif

View file

@ -87,6 +87,7 @@ void win_key_callback(GLFWwindow *w, int key, int scancode, int action, int mods
char keybuf[10]; char keybuf[10];
if (key > 289 && key < 302) { if (key > 289 && key < 302) {
sprintf(keybuf, "f%d", key-289); sprintf(keybuf, "f%d", key-289);
strcat(keystr, keybuf);
} else { } else {
switch(key) { switch(key) {
case GLFW_KEY_ENTER: case GLFW_KEY_ENTER:

View file

@ -11,6 +11,7 @@
#include "log.h" #include "log.h"
#include "input.h" #include "input.h"
#include "gameobject.h" #include "gameobject.h"
#include "openglrender.h"
#include "s7.h" #include "s7.h"
@ -69,7 +70,7 @@ s7_pointer s7_gui_text(s7_scheme *sc, s7_pointer args) {
s7_pointer s7_settings_cmd(s7_scheme *sc, s7_pointer args) { s7_pointer s7_settings_cmd(s7_scheme *sc, s7_pointer args) {
int cmd = s7_integer(s7_car(args)); int cmd = s7_integer(s7_car(args));
double val = s7_real(s7_cadr(args)); double val = s7_real(s7_cadr(args));
YughInfo("Changing a setting.");
switch(cmd) { switch(cmd) {
case 0: // render fps case 0: // render fps
renderMS = val; renderMS = val;
@ -82,6 +83,10 @@ s7_pointer s7_settings_cmd(s7_scheme *sc, s7_pointer args) {
case 2: case 2:
physMS = val; physMS = val;
break; break;
case 3:
debug_draw_phys(val);
break;
} }
return args; return args;
@ -277,14 +282,13 @@ s7_pointer s7_set_body_pos(s7_scheme *sc, s7_pointer args) {
} }
s7_pointer s7_phys_cmd(s7_scheme *sc, s7_pointer args) { s7_pointer s7_phys_cmd(s7_scheme *sc, s7_pointer args) {
int cmd = s7_integer(s7_car(args)); int go = s7_integer(s7_car(args));
s7_pointer env = s7_cadr(args); int cmd = s7_integer(s7_cadr(args));
s7_pointer env = s7_caddr(args);
switch(cmd) { if (go == -1) return;
case 0:
phys2d_add_begin_handler(env); phys2d_add_handler_type(cmd, get_gameobject_from_id(go), env);
break;
}
} }
#define S7_FUNC(NAME, ARGS) s7_define_function(s7, #NAME, s7_ ##NAME, ARGS, 0, 0, "") #define S7_FUNC(NAME, ARGS) s7_define_function(s7, #NAME, s7_ ##NAME, ARGS, 0, 0, "")
@ -309,6 +313,6 @@ void ffi_load() {
S7_FUNC(set_pawn, 1); S7_FUNC(set_pawn, 1);
S7_FUNC(set_body, 3); S7_FUNC(set_body, 3);
S7_FUNC(set_body_pos, 4); S7_FUNC(set_body_pos, 4);
S7_FUNC(phys_cmd, 2); S7_FUNC(phys_cmd, 3);
} }

View file

@ -62,6 +62,10 @@ struct sprite *tsprite = NULL;
static unsigned int projUBO; static unsigned int projUBO;
void debug_draw_phys(int draw) {
debugDrawPhysics = draw;
}
void openglInit() void openglInit()
{ {
if (!mainwin) { if (!mainwin) {
@ -129,6 +133,10 @@ void openglRender(struct window *window)
//script_call_sym(window->gui_cb); //script_call_sym(window->gui_cb);
call_gui(); call_gui();
//// DEBUG
if (debugDrawPhysics)
gameobject_draw_debugs();
///// Sprites ///// Sprites
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
shader_use(spriteShader); shader_use(spriteShader);

View file

@ -42,7 +42,8 @@ void openglRender(struct window *window);
void openglInit3d(struct window *window); void openglInit3d(struct window *window);
void openglRender3d(struct window *window, struct mCamera *camera); void openglRender3d(struct window *window, struct mCamera *camera);
void BindUniformBlock(GLuint shaderID, const char *bufferName, void debug_draw_phys(int draw);
GLuint bufferBind);
void BindUniformBlock(GLuint shaderID, const char *bufferName, GLuint bufferBind);
#endif #endif

View file

@ -90,8 +90,29 @@
(define (body_pos! body x y) (set_body_pos body 0 x y)) (define (body_pos! body x y) (set_body_pos body 0 x y))
(define (body_move! body x y) (set_body_pos body 1 x y)) (define (body_move! body x y) (set_body_pos body 1 x y))
(define-macro (collide . expr) (define (b2i val) (if (eq? val #f) 0 1))
(define (dbg_draw_phys val) (settings_cmd 3 (b2i val)))
(define-macro (register-phys type body . expr)
(let ((f (gensym))) (let ((f (gensym)))
`(begin `(begin
(define (,f) (begin . ,expr)) (define (,f) (begin . ,expr))
(phys_cmd 0 ,f)))) (phys_cmd ,body ,(case type
((collide) 0)
((separate) 3)) ,f))))
(define (collide . expr)
(register-phys collide body expr))
(define-macro (separate . expr)
`(register-phys separate body ,@expr))
(define-macro (not! var)
`(set! ,var (not ,var)))
(define-macro* (define-script name (lets ()) . expr )
`(define* (,name (gameobject -1))
(let ((body gameobject)
,@lets)
,@expr
(curlet))))

View file

@ -8,12 +8,14 @@ uniform int thickness;
void main() void main()
{ {
// int tt = thickness + 1; // int tt = thickness + 1;
float R1 = 1.f; float R1 = 1.f;
float R2 = 1.f - (thickness / radius); float R2 = 1.f - (thickness / radius);
float dist = sqrt(dot(coords, coords)); float dist = sqrt(dot(coords, coords));
if (dist <= R2 || dist >= R1) if (dist <= R2 || dist >= R1)
discard; discard;
/* /*
float smoother = 0.01f - (radius * 0.00003f); float smoother = 0.01f - (radius * 0.00003f);
float sm = smoothstep(R1, R1-smoother, dist); float sm = smoothstep(R1, R1-smoother, dist);

View file

@ -1,5 +1,5 @@
#version 330 core #version 330 core
layout (location = 0) in vec2 vertex; layout (location = 0) in vec4 vertex;
out vec2 coords; out vec2 coords;
layout (std140) uniform Projection layout (std140) uniform Projection
@ -10,4 +10,5 @@ layout (std140) uniform Projection
void main() void main()
{ {
gl_Position = projection * vec4(vertex.xy, 0.0, 1.0); gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
coords = vertex.zw;
} }