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"
cpBody *ballBody = NULL;
cpSpace *space = NULL;
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)
{
shape->go = go;
cpShapeSetCollisionType(shape->shape, go);
YughInfo("Added shape type %d", go);
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)
{
box->shape.shape =
cpSpaceAddShape(space,
cpBoxShapeNew(go->body, box->w, box->h, box->r));
box->shape.shape = cpSpaceAddShape(space, cpBoxShapeNew(go->body, box->w, box->h, box->r));
init_phys2dshape(&box->shape, go);
phys2d_applybox(box);
}
@ -179,9 +178,7 @@ void phys2d_polyinit(struct phys2d_poly *poly, struct gameobject *go)
{
cpTransform T = { 0 };
poly->shape.shape =
cpSpaceAddShape(space,
cpPolyShapeNew(go->body, 0, NULL, T,
poly->radius));
cpSpaceAddShape(space, cpPolyShapeNew(go->body, 0, NULL, T, poly->radius));
init_phys2dshape(&poly->shape, go);
phys2d_applypoly(poly);
}
@ -231,14 +228,10 @@ struct phys2d_edge *Make2DEdge(struct gameobject *go)
void phys2d_edgeinit(struct phys2d_edge *edge, struct gameobject *go)
{
edge->shapes[0] =
cpSpaceAddShape(space,
cpSegmentShapeNew(go->body, cpvzero, cpvzero,
edge->thickness));
cpSpaceAddShape(space, cpSegmentShapeNew(go->body, cpvzero, cpvzero, edge->thickness));
edge->shape.go = go;
phys2d_edgeshapeapply(&edge->shape, edge->shapes[0]);
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);
for (int i = 0; i < edge->n; i++) {
//ImGui::PushID(i);
for (int i = 0; i < edge->n; i++)
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);
@ -304,9 +294,7 @@ void phys2d_applycircle(struct phys2d_circle *circle)
cpCircleShapeSetRadius(circle->shape.shape, radius);
cpCircleShapeSetOffset(circle->shape.shape, offset);
cpBodySetMoment(circle->shape.go->body,
cpMomentForCircle(circle->shape.go->mass, 0, radius,
offset));
cpBodySetMoment(circle->shape.go->body, cpMomentForCircle(circle->shape.go->mass, 0, radius, offset));
}
void phys2d_applyseg(struct phys2d_segment *seg)
@ -461,18 +449,67 @@ void phys2d_dbgdrawedge(struct phys2d_edge *edge)
}
}
s7_pointer *cbs;
static cpBool s7_phys_cb(cpArbiter *arb, cpSpace *space, void *data) {
s7_pointer *cb = data;
script_call_sym(*cb);
void phys2d_reindex_body(cpBody *body) {
cpSpaceReindexShapesForBody(space, body);
}
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 cpSpace *space;
struct phys_cbs {
s7_pointer begin;
s7_pointer separate;
};
struct phys2d_shape {
cpShape *shape;
struct gameobject *go;
@ -95,8 +100,10 @@ void phys2d_init();
void phys2d_update(float deltaT);
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 phys2d_reindex_body(cpBody *body);
#endif

View file

@ -3,6 +3,7 @@
#include "openglrender.h"
#include "shader.h"
#include "log.h"
static uint32_t circleVBO;
static uint32_t circleVAO;
@ -68,10 +69,10 @@ void draw_circle(int x, int y, float radius, int pixels)
shader_use(circleShader);
float verts[] = {
x - radius, y - radius,
x + radius, y - radius,
x - radius, y + radius,
x + radius, y + radius,
x - radius, y - radius, -1, -1,
x + radius, y - radius, 1, -1,
x - radius, y + radius, -1, 1,
x + radius, y + radius, 1, 1
};
glBindBuffer(GL_ARRAY_BUFFER, circleVBO);
@ -82,7 +83,7 @@ void draw_circle(int x, int y, float radius, int pixels)
glBindVertexArray(circleVAO);
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);
}

View file

@ -57,7 +57,8 @@ struct gameobject *MakeGameobject()
gameobject_setpickcolor(&go);
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);
@ -151,13 +152,6 @@ void gameobject_init(struct gameobject *go, FILE * fprefab)
int n;
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);
arrput(go->components, components[n]);
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)
{
cpVect p = cpBodyGetPosition(go->body);
p.x += xs * deltaT;
p.y += ys * deltaT;
cpBodySetPosition(go->body, p);
phys2d_reindex_body(go->body);
}
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);
a += as * deltaT;
cpBodySetAngle(go->body, a);
phys2d_reindex_body(go->body);
}
void gameobject_setangle(struct gameobject *go, float angle) {
cpBodySetAngle(go->body, angle);
phys2d_reindex_body(go->body);
}
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.y = y;
cpBodySetPosition(go->body, p);
}
void update_gameobjects() {
for (int i = 0; i < arrlen(gameobjects); i++)
gameobject_update(&gameobjects[i]);
phys2d_reindex_body(go->body);
}
void object_gui(struct gameobject *go)
{
float temp_pos[2];
@ -323,3 +313,13 @@ void object_gui(struct gameobject *go)
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 <stdbool.h>
#include <chipmunk/chipmunk.h>
#include "2dphysics.h"
struct shader;
struct sprite;
@ -23,6 +24,10 @@ struct editor {
char rootPrefabName[MAXNAME];
};
struct go_temp {
struct phys_cbs phys_cbs;
};
struct gameobject {
struct mTransform transform;
struct editor editor;
@ -33,7 +38,7 @@ struct gameobject {
float f; /* friction */
float e; /* elasticity */
struct component *components;
char *script;
struct phys_cbs *cbs;
};
extern struct gameobject *gameobjects;
@ -62,14 +67,13 @@ void gameobject_revertprefab(struct gameobject *go);
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_rotate(struct gameobject *go, float as);
void gameobject_setangle(struct gameobject *go, float angle);
void gameobject_setpos(struct gameobject *go, float x, float y);
void gameobject_draw_debugs();
void object_gui(struct gameobject *go);
#endif

View file

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

View file

@ -11,6 +11,7 @@
#include "log.h"
#include "input.h"
#include "gameobject.h"
#include "openglrender.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) {
int cmd = s7_integer(s7_car(args));
double val = s7_real(s7_cadr(args));
YughInfo("Changing a setting.");
switch(cmd) {
case 0: // render fps
renderMS = val;
@ -82,6 +83,10 @@ s7_pointer s7_settings_cmd(s7_scheme *sc, s7_pointer args) {
case 2:
physMS = val;
break;
case 3:
debug_draw_phys(val);
break;
}
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) {
int cmd = s7_integer(s7_car(args));
s7_pointer env = s7_cadr(args);
int go = s7_integer(s7_car(args));
int cmd = s7_integer(s7_cadr(args));
s7_pointer env = s7_caddr(args);
switch(cmd) {
case 0:
phys2d_add_begin_handler(env);
break;
}
if (go == -1) return;
phys2d_add_handler_type(cmd, get_gameobject_from_id(go), env);
}
#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_body, 3);
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;
void debug_draw_phys(int draw) {
debugDrawPhysics = draw;
}
void openglInit()
{
if (!mainwin) {
@ -129,6 +133,10 @@ void openglRender(struct window *window)
//script_call_sym(window->gui_cb);
call_gui();
//// DEBUG
if (debugDrawPhysics)
gameobject_draw_debugs();
///// Sprites
glDepthFunc(GL_LESS);
shader_use(spriteShader);

View file

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

View file

@ -90,8 +90,29 @@
(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-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)))
`(begin
(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()
{
// int tt = thickness + 1;
float R1 = 1.f;
float R2 = 1.f - (thickness / radius);
float dist = sqrt(dot(coords, coords));
if (dist <= R2 || dist >= R1)
discard;
/*
float smoother = 0.01f - (radius * 0.00003f);
float sm = smoothstep(R1, R1-smoother, dist);

View file

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