Physics edges

This commit is contained in:
John Alanbrook 2023-01-26 03:32:58 +00:00
parent 9303fb63cf
commit 68850b558a
11 changed files with 316 additions and 274 deletions

View file

@ -73,7 +73,7 @@ SEM = 0.0.1
COM != git rev-parse --short HEAD COM != git rev-parse --short HEAD
VER = $(SEM)-$(COM) VER = $(SEM)-$(COM)
COMPILER_FLAGS = $(includeflag) $(QFLAGS) -MD $(WARNING_FLAGS) -DVER=\"$(VER)\" -DINFO=\"$(INFO)\" -c $< -o $@ COMPILER_FLAGS = $(includeflag) $(QFLAGS) -MD $(WARNING_FLAGS) -DCP_USE_DOUBLES=0 -DVER=\"$(VER)\" -DINFO=\"$(INFO)\" -c $< -o $@
LIBPATH = -L$(BIN) LIBPATH = -L$(BIN)

View file

@ -10,6 +10,7 @@
#include <math.h> #include <math.h>
#include <chipmunk/chipmunk_unsafe.h> #include <chipmunk/chipmunk_unsafe.h>
#include "stb_ds.h" #include "stb_ds.h"
#include <assert.h>
#include "script.h" #include "script.h"
@ -158,40 +159,19 @@ void phys2d_dbgdrawcircle(struct phys2d_circle *circle)
phys2d_dbgdrawcpcirc((cpCircleShape *)circle->shape.shape); phys2d_dbgdrawcpcirc((cpCircleShape *)circle->shape.shape);
} }
void phys2d_applycircle(struct phys2d_circle *circle)
/*********** SEGMENT2D **************/
struct phys2d_segment *Make2DSegment(int go)
{ {
struct phys2d_segment *new = malloc(sizeof(struct phys2d_segment)); struct gameobject *go = id2go(circle->shape.go);
new->thickness = 1.f; float radius = circle->radius * go->scale;
new->a[0] = 0.f; float s = go->scale;
new->a[1] = 0.f; cpVect offset = { circle->offset.x * s, circle->offset.y * s };
new->b[0] = 0.f;
new->b[1] = 0.f;
new->shape.shape = cpSpaceAddShape(space, cpSegmentShapeNew(id2go(go)->body, cpvzero, cpvzero, new->thickness)); cpCircleShapeSetRadius(circle->shape.shape, radius);
new->shape.debugdraw = phys2d_dbgdrawseg; cpCircleShapeSetOffset(circle->shape.shape, offset);
init_phys2dshape(&new->shape, go, new); //cpBodySetMoment(go->body, cpMomentForCircle(go->mass, 0, radius, offset));
return new;
} }
void phys2d_segdel(struct phys2d_segment *seg)
{
phys2d_shape_del(&seg->shape);
}
void segment_gui(struct phys2d_segment *seg)
{
nuke_property_float2("a", 0.f, seg->a, 1.f, 0.01f, 0.01f);
nuke_property_float2("b", 0.f, seg->b, 1.f, 0.01f, 0.01f);
phys2d_applyseg(seg);
}
/************* BOX2D ************/ /************* BOX2D ************/
struct phys2d_box *Make2DBox(int go) struct phys2d_box *Make2DBox(int go)
@ -230,209 +210,18 @@ void phys2d_applybox(struct phys2d_box *box)
{ {
float s = id2go(box->shape.go)->scale; float s = id2go(box->shape.go)->scale;
cpTransform T = { 0 }; cpTransform T = { 0 };
T.a = s; T.a = s * cos(box->rotation);
T.d = s; T.b = -sin(box->rotation);
T.c = sin(box->rotation);
T.d = s * cos(box->rotation);
T.tx = box->offset[0] * s; T.tx = box->offset[0] * s;
T.ty = box->offset[1] * s; T.ty = box->offset[1] * s;
float hh = box->h / 2.f; float hh = box->h / 2.f;
float hw = box->w / 2.f; float hw = box->w / 2.f;
cpVect verts[4] = cpVect verts[4] = { { -hw, -hh }, { hw, -hh }, { hw, hh }, { -hw, hh } };
{ { -hw, -hh }, { hw, -hh }, { hw, hh }, { -hw, hh } };
cpPolyShapeSetVerts(box->shape.shape, 4, verts, T); cpPolyShapeSetVerts(box->shape.shape, 4, verts, T);
cpPolyShapeSetRadius(box->shape.shape, box->r); cpPolyShapeSetRadius(box->shape.shape, box->r);
} }
/************** POLYGON ************/
struct phys2d_poly *Make2DPoly(int go)
{
struct phys2d_poly *new = malloc(sizeof(struct phys2d_poly));
new->n = 0;
new->points = NULL;
new->radius = 0.f;
cpTransform T = { 0 };
new->shape.shape = cpSpaceAddShape(space, cpPolyShapeNew(id2go(go)->body, 0, NULL, T, new->radius));
init_phys2dshape(&new->shape, go, new);
new->shape.debugdraw = phys2d_dbgdrawpoly;
phys2d_applypoly(new);
return new;
}
void phys2d_polydel(struct phys2d_poly *poly)
{
phys2d_shape_del(&poly->shape);
}
void phys2d_polyaddvert(struct phys2d_poly *poly)
{
poly->n++;
float *oldpoints = poly->points;
poly->points = calloc(2 * poly->n, sizeof(float));
memcpy(poly->points, oldpoints, sizeof(float) * 2 * (poly->n - 1));
free(oldpoints);
}
void poly_gui(struct phys2d_poly *poly)
{
if (nuke_btn("Add Poly Vertex")) phys2d_polyaddvert(poly);
for (int i = 0; i < poly->n; i++) {
nuke_property_float2("#P", 0.f, &poly->points[i*2], 1.f, 0.1f, 0.1f);
}
nuke_property_float("Radius", 0.01f, &poly->radius, 1000.f, 1.f, 0.1f);
phys2d_applypoly(poly);
}
/****************** EDGE 2D**************/
struct phys2d_edge *Make2DEdge(int go)
{
struct phys2d_edge *new = malloc(sizeof(struct phys2d_edge));
new->n = 2;
new->points = calloc(2 * 2, sizeof(float));
new->thickness = 0.f;
new->shapes = malloc(sizeof(cpShape *));
new->shapes[0] = cpSpaceAddShape(space, cpSegmentShapeNew(id2go(go)->body, cpvzero, cpvzero, new->thickness));
new->shape.go = go;
phys2d_edgeshapeapply(&new->shape, new->shapes[0]);
phys2d_applyedge(new);
return new;
}
void phys2d_edgedel(struct phys2d_edge *edge)
{
phys2d_shape_del(&edge->shape);
}
void phys2d_edgeshapeapply(struct phys2d_shape *mshape, cpShape * shape)
{
cpShapeSetFriction(shape, id2go(mshape->go)->f);
cpShapeSetElasticity(shape, id2go(mshape->go)->e);
}
void phys2d_edgeaddvert(struct phys2d_edge *edge)
{
edge->n++;
float *oldp = edge->points;
edge->points = calloc(edge->n * 2, sizeof(float));
memcpy(edge->points, oldp, sizeof(float) * 2 * (edge->n - 1));
cpShape **oldshapes = edge->shapes;
edge->shapes = malloc(sizeof(cpShape *) * (edge->n - 1));
memcpy(edge->shapes, oldshapes, sizeof(cpShape *) * (edge->n - 2));
cpVect a =
{ edge->points[(edge->n - 2) * 2],
edge->points[(edge->n - 2) * 2 + 1] };
cpVect b =
{ edge->points[(edge->n - 1) * 2],
edge->points[(edge->n - 1) * 2 + 1] };
edge->shapes[edge->n - 2] = cpSpaceAddShape(space, cpSegmentShapeNew(id2go(edge->shape.go)->body, a, b, edge->thickness));
phys2d_edgeshapeapply(&edge->shape, edge->shapes[edge->n - 2]);
free(oldp);
free(oldshapes);
}
void edge_gui(struct phys2d_edge *edge)
{
if (nuke_btn("Add Edge Vertex")) phys2d_edgeaddvert(edge);
for (int i = 0; i < edge->n; i++)
nuke_property_float2("E", 0.f, &edge->points[i*2], 1.f, 0.01f, 0.01f);
nuke_property_float("Thickness", 0.01f, &edge->thickness, 1.f, 0.01f, 0.01f);
phys2d_applyedge(edge);
}
void phys2d_applycircle(struct phys2d_circle *circle)
{
struct gameobject *go = id2go(circle->shape.go);
float radius = circle->radius * go->scale;
float s = go->scale;
cpVect offset = { circle->offset.x * s, circle->offset.y * s };
cpCircleShapeSetRadius(circle->shape.shape, radius);
cpCircleShapeSetOffset(circle->shape.shape, offset);
cpBodySetMoment(go->body, cpMomentForCircle(go->mass, 0, radius, offset));
}
void phys2d_applyseg(struct phys2d_segment *seg)
{
float s = id2go(seg->shape.go)->scale;
cpVect a = { seg->a[0] * s, seg->a[1] * s };
cpVect b = { seg->b[0] * s, seg->b[1] * s };
cpSegmentShapeSetEndpoints(seg->shape.shape, a, b);
cpSegmentShapeSetRadius(seg->shape.shape, seg->thickness * s);
}
void phys2d_applypoly(struct phys2d_poly *poly)
{
cpVect verts[poly->n];
for (int i = 0; i < poly->n; i++) {
verts[i].x = poly->points[i * 2];
verts[i].y = poly->points[i * 2 + 1];
}
CP_CONVEX_HULL(poly->n, verts, hullCount, hullVerts);
float s = id2go(poly->shape.go)->scale;
cpTransform T = { 0 };
T.a = s;
T.d = s;
cpPolyShapeSetVerts(poly->shape.shape, hullCount, hullVerts, T);
cpPolyShapeSetRadius(poly->shape.shape, poly->radius);
}
void phys2d_applyedge(struct phys2d_edge *edge)
{
float s = id2go(edge->shape.go)->scale;
for (int i = 0; i < edge->n - 1; i++) {
cpVect a =
{ edge->points[i * 2] * s, edge->points[i * 2 + 1] * s };
cpVect b =
{ edge->points[i * 2 + 2] * s, edge->points[i * 2 + 3] * s };
cpSegmentShapeSetEndpoints(edge->shapes[i], a, b);
cpSegmentShapeSetRadius(edge->shapes[i], edge->thickness);
}
}
void phys2d_dbgdrawseg(struct phys2d_segment *seg)
{
cpVect p = cpBodyGetPosition(cpShapeGetBody(seg->shape.shape));
cpVect a = cpSegmentShapeGetA(seg->shape.shape);
cpVect b = cpSegmentShapeGetB(seg->shape.shape);
float angle = cpBodyGetAngle(cpShapeGetBody(seg->shape.shape));
float ad = sqrt(pow(a.x, 2.f) + pow(a.y, 2.f));
float bd = sqrt(pow(b.x, 2.f) + pow(b.y, 2.f));
float aa = atan2(a.y, a.x) + angle;
float ba = atan2(b.y, b.x) + angle;
draw_line(ad * cos(aa) + p.x, ad * sin(aa) + p.y, bd * cos(ba) + p.x, bd * sin(ba) + p.y, shape_color(seg->shape.shape));
}
void phys2d_dbgdrawbox(struct phys2d_box *box) void phys2d_dbgdrawbox(struct phys2d_box *box)
{ {
int n = cpPolyShapeGetCount(box->shape.shape); int n = cpPolyShapeGetCount(box->shape.shape);
@ -450,22 +239,70 @@ void phys2d_dbgdrawbox(struct phys2d_box *box)
draw_poly(points, n, shape_color(box->shape.shape)); draw_poly(points, n, shape_color(box->shape.shape));
} }
/************** POLYGON ************/
struct phys2d_poly *Make2DPoly(int go)
{
struct phys2d_poly *new = malloc(sizeof(struct phys2d_poly));
arrsetlen(new->points, 0);
new->radius = 0.f;
new->shape.shape = cpSpaceAddShape(space, cpPolyShapeNewRaw(id2go(go)->body, 0, new->points, new->radius));
new->shape.debugdraw = phys2d_dbgdrawpoly;
init_phys2dshape(&new->shape, go, new);
return new;
}
void phys2d_polydel(struct phys2d_poly *poly)
{
arrfree(poly->points);
phys2d_shape_del(&poly->shape);
}
void phys2d_polyaddvert(struct phys2d_poly *poly)
{
arrput(poly->points, cpvzero);
}
void poly_gui(struct phys2d_poly *poly)
{
}
void phys2d_poly_setverts(struct phys2d_poly *poly, cpVect *verts)
{
arrfree(poly->points);
poly->points = verts;
phys2d_applypoly(poly);
}
void phys2d_applypoly(struct phys2d_poly *poly)
{
if (arrlen(poly->points) <= 0) return;
float s = id2go(poly->shape.go)->scale;
cpTransform T = { 0 };
T.a = s;
T.d = s;
cpPolyShapeSetVerts(poly->shape.shape, arrlen(poly->points), poly->points, T);
cpPolyShapeSetRadius(poly->shape.shape, poly->radius);
}
void phys2d_dbgdrawpoly(struct phys2d_poly *poly) void phys2d_dbgdrawpoly(struct phys2d_poly *poly)
{ {
float *color = shape_color(poly->shape.shape); float *color = shape_color(poly->shape.shape);
int n = arrlen(poly->points);
cpVect b = cpBodyGetPosition(cpShapeGetBody(poly->shape.shape)); cpVect b = cpBodyGetPosition(cpShapeGetBody(poly->shape.shape));
float angle = cpBodyGetAngle(cpShapeGetBody(poly->shape.shape)); float angle = cpBodyGetAngle(cpShapeGetBody(poly->shape.shape));
float s = id2go(poly->shape.go)->scale; float s = id2go(poly->shape.go)->scale;
for (int i = 0; i < poly->n; i++) { for (int i = 0; i < n; i++) {
float d = sqrt(pow(poly->points[i * 2] * s, 2.f) + pow(poly->points[i * 2 + 1] * s, 2.f)); float d = sqrt(pow(poly->points[i * 2].x * s, 2.f) + pow(poly->points[i * 2].y* s, 2.f));
float a = atan2(poly->points[i * 2 + 1], poly->points[i * 2]) + angle; float a = atan2(poly->points[i * 2].y, poly->points[i * 2].x) + angle;
draw_point(b.x + d * cos(a), b.y + d * sin(a), 3, color); draw_point(b.x + d * cos(a), b.y + d * sin(a), 3, color);
} }
if (poly->n >= 3) { if (arrlen(poly->points) >= 3) {
int n = cpPolyShapeGetCount(poly->shape.shape); int n = cpPolyShapeGetCount(poly->shape.shape);
float points[n * 2]; float points[n * 2];
@ -481,32 +318,111 @@ void phys2d_dbgdrawpoly(struct phys2d_poly *poly)
} }
} }
/****************** EDGE 2D**************/
struct phys2d_edge *Make2DEdge(int go)
{
struct phys2d_edge *new = malloc(sizeof(struct phys2d_edge));
new->points = NULL;
arrsetlen(new->points, 0);
new->thickness = 0.f;
new->shapes = NULL;
arrsetlen(new->shapes, 0);
new->shape.go = go;
new->shape.data = new;
new->shape.debugdraw = phys2d_dbgdrawedge;
phys2d_applyedge(new);
return new;
}
void phys2d_edgedel(struct phys2d_edge *edge)
{
phys2d_shape_del(&edge->shape);
}
void phys2d_edgeaddvert(struct phys2d_edge *edge)
{
arrput(edge->points, cpvzero);
if (arrlen(edge->points) > 1)
arrput(edge->shapes, cpSpaceAddShape(space, cpSegmentShapeNew(id2go(edge->shape.go)->body, cpvzero, cpvzero, edge->thickness)));
phys2d_applyedge(edge);
}
void phys2d_edge_rmvert(struct phys2d_edge *edge, int index)
{
assert(arrlen(edge->points) > index && index >= 0);
arrdel(edge->points, index);
cpSegmentShapeSetEndpoints(edge->shapes[index-1], edge->points[index-1], edge->points[index]);
cpSpaceRemoveShape(space, edge->shapes[index-1]);
arrdel(edge->shapes, index-1);
phys2d_applyedge(edge);
}
phys2d_edge_setvert(struct phys2d_edge *edge, int index, cpVect val)
{
assert(arrlen(edge->points) > index && index >= 0);
edge->points[index] = val;
phys2d_applyedge(edge);
}
void phys2d_applyedge(struct phys2d_edge *edge)
{
float s = id2go(edge->shape.go)->scale;
for (int i = 0; i < arrlen(edge->shapes); i++) {
cpVect a = edge->points[i];
cpVect b = edge->points[i+1];
a.x *= s;
a.y *= s;
b.x *= s;
b.y *= s;
cpSegmentShapeSetEndpoints(edge->shapes[i], a, b);
cpSegmentShapeSetRadius(edge->shapes[i], edge->thickness);
cpShapeSetUserData(edge->shapes[i], &edge->shape);
cpShapeSetCollisionType(edge->shapes[i], edge->shape.go);
cpShapeSetFriction(edge->shapes[i], id2go(edge->shape.go)->f);
cpShapeSetElasticity(edge->shapes[i], id2go(edge->shape.go)->e);
}
cpSpaceReindexShapesForBody(space, id2go(edge->shape.go)->body);
}
void phys2d_dbgdrawedge(struct phys2d_edge *edge) void phys2d_dbgdrawedge(struct phys2d_edge *edge)
{ {
float *color =shape_color(edge->shape.shape); edge->draws++;
if (edge->draws > 1) {
if (edge->draws >= arrlen(edge->shapes))
edge->draws = 0;
cpVect p = cpBodyGetPosition(cpShapeGetBody(edge->shape.shape)); return;
}
if (arrlen(edge->shapes) < 1) return;
cpVect p = cpBodyGetPosition(cpShapeGetBody(edge->shapes[0]));
float s = id2go(edge->shape.go)->scale; float s = id2go(edge->shape.go)->scale;
float angle = cpBodyGetAngle(cpShapeGetBody(edge->shape.shape)); float angle = cpBodyGetAngle(cpShapeGetBody(edge->shapes[0]));
for (int i = 0; i < edge->n; i++) { cpVect drawpoints[arrlen(edge->points)];
float d = sqrt(pow(edge->points[i * 2] * s, 2.f) + pow(edge->points[i * 2 + 1] * s, 2.f));
float a = atan2(edge->points[i * 2 + 1], edge->points[i * 2]) + angle; for (int i = 0; i < arrlen(edge->points); i++) {
draw_point(p.x + d * cos(a), p.y + d * sin(a), 3, color); float d = sqrt(pow(edge->points[i].x*s, 2.f) + pow(edge->points[i].y*s, 2.f));
float a = atan2(edge->points[i].y, edge->points[i].x) + angle;
drawpoints[i].x = p.x + d*cos(a);
drawpoints[i].y = p.y + d*sin(a);
} }
for (int i = 0; i < edge->n - 1; i++) { draw_edge(drawpoints, arrlen(edge->points), trigger_color);
cpVect a = cpSegmentShapeGetA(edge->shapes[i]); draw_points(drawpoints, arrlen(edge->points), 2, kinematic_color);
cpVect b = cpSegmentShapeGetB(edge->shapes[i]);
float ad = sqrt(pow(a.x, 2.f) + pow(a.y, 2.f));
float bd = sqrt(pow(b.x, 2.f) + pow(b.y, 2.f));
float aa = atan2(a.y, a.x) + angle;
float ba = atan2(b.y, b.x) + angle;
draw_line(ad * cos(aa) + p.x, ad * sin(aa) + p.y, bd * cos(ba) + p.x, bd * sin(ba) + p.y, color);
}
} }
/************ COLLIDER ****************/
void shape_enabled(struct phys2d_shape *shape, int enabled) void shape_enabled(struct phys2d_shape *shape, int enabled)
{ {
if (enabled) if (enabled)

View file

@ -23,12 +23,14 @@ struct phys2d_shape {
void (*debugdraw)(void *data); void (*debugdraw)(void *data);
}; };
/* Circles are the fastest collier type */
struct phys2d_circle { struct phys2d_circle {
float radius; float radius;
cpVect offset; cpVect offset;
struct phys2d_shape shape; struct phys2d_shape shape;
}; };
/* A single segment */
struct phys2d_segment { struct phys2d_segment {
float a[2]; float a[2];
float b[2]; float b[2];
@ -36,27 +38,31 @@ struct phys2d_segment {
struct phys2d_shape shape; struct phys2d_shape shape;
}; };
/* A convex polygon; defined as the convex hull around the given set of points */
struct phys2d_poly {
cpVect *points;
float radius;
struct phys2d_shape shape;
};
/* A box shape; a type of a polygon collider */
struct phys2d_box { struct phys2d_box {
float w; float w;
float h; float h;
float offset[2]; float offset[2];
float rotation;
float r; float r;
struct phys2d_shape shape; struct phys2d_shape shape;
}; };
/* An edge with no volume. Cannot collide with each other. Join to make levels. */
struct phys2d_edge { struct phys2d_edge {
int n; cpVect *points;
float *points;
float thickness; float thickness;
cpShape **shapes; cpShape **shapes;
int closed; /* True if the first and last points should be connected */
struct phys2d_shape shape; struct phys2d_shape shape;
}; int draws;
struct phys2d_poly {
int n;
float *points;
float radius;
struct phys2d_shape shape;
}; };
struct phys2d_circle *Make2DCircle(int go); struct phys2d_circle *Make2DCircle(int go);
@ -65,12 +71,6 @@ void phys2d_applycircle(struct phys2d_circle *circle);
void phys2d_dbgdrawcircle(struct phys2d_circle *circle); void phys2d_dbgdrawcircle(struct phys2d_circle *circle);
void circle_gui(struct phys2d_circle *circle); void circle_gui(struct phys2d_circle *circle);
struct phys2d_segment *Make2DSegment(int go);
void phys2d_segdel(struct phys2d_segment *seg);
void phys2d_applyseg(struct phys2d_segment *seg);
void phys2d_dbgdrawseg(struct phys2d_segment *seg);
void segment_gui(struct phys2d_segment *seg);
struct phys2d_box *Make2DBox(int go); struct phys2d_box *Make2DBox(int go);
void phys2d_boxdel(struct phys2d_box *box); void phys2d_boxdel(struct phys2d_box *box);
void phys2d_applybox(struct phys2d_box *box); void phys2d_applybox(struct phys2d_box *box);
@ -82,14 +82,15 @@ void phys2d_polydel(struct phys2d_poly *poly);
void phys2d_applypoly(struct phys2d_poly *poly); void phys2d_applypoly(struct phys2d_poly *poly);
void phys2d_dbgdrawpoly(struct phys2d_poly *poly); void phys2d_dbgdrawpoly(struct phys2d_poly *poly);
void phys2d_polyaddvert(struct phys2d_poly *poly); void phys2d_polyaddvert(struct phys2d_poly *poly);
void phys2d_poly_setverts(struct phys2d_poly *poly, cpVect *verts);
void poly_gui(struct phys2d_poly *poly); void poly_gui(struct phys2d_poly *poly);
struct phys2d_edge *Make2DEdge(int go); struct phys2d_edge *Make2DEdge(int go);
void phys2d_edgedel(struct phys2d_edge *edge); void phys2d_edgedel(struct phys2d_edge *edge);
void phys2d_applyedge(struct phys2d_edge *edge); void phys2d_applyedge(struct phys2d_edge *edge);
void phys2d_edgeshapeapply(struct phys2d_shape *mshape, cpShape * shape);
void phys2d_dbgdrawedge(struct phys2d_edge *edge); void phys2d_dbgdrawedge(struct phys2d_edge *edge);
void phys2d_edgeaddvert(struct phys2d_edge *edge); void phys2d_edgeaddvert(struct phys2d_edge *edge);
void phys2d_edge_rmvert(struct phys2d_edge *edge, int index);
void edge_gui(struct phys2d_edge *edge); void edge_gui(struct phys2d_edge *edge);

View file

@ -1,6 +1,8 @@
#ifndef DEBUG_GUI_H #ifndef DEBUG_GUI_H
#define DEBUG_GUI_H #define DEBUG_GUI_H
#define static_assert(pred) switch(0){case 0:case pred:;}
extern unsigned long long triCount; extern unsigned long long triCount;
void resetTriangles(); void resetTriangles();

View file

@ -4,6 +4,10 @@
#include "shader.h" #include "shader.h"
#include "log.h" #include "log.h"
#include <assert.h>
#include "debug.h"
#include "stb_ds.h"
static uint32_t circleVBO; static uint32_t circleVBO;
static uint32_t circleVAO; static uint32_t circleVAO;
@ -59,9 +63,20 @@ void draw_line(int x1, int y1, int x2, int y2, float *color)
draw_poly(verts, 2, color); draw_poly(verts, 2, color);
} }
void draw_edge(float *points, int n, float *color) void draw_edge(cpVect *points, int n, float *color)
{ {
draw_poly(points, n, color); static_assert(sizeof(cpVect) == 2*sizeof(float));
shader_use(rectShader);
shader_setvec3(rectShader, "linecolor", color);
glBindBuffer(GL_ARRAY_BUFFER, rectVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * n * 2, points, GL_DYNAMIC_DRAW);
glBindVertexArray(rectVAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
shader_setfloat(rectShader, "alpha", 1.f);
glDrawArrays(GL_LINE_STRIP, 0, n);
} }
void draw_circle(int x, int y, float radius, int pixels, float *color, int fill) void draw_circle(int x, int y, float radius, int pixels, float *color, int fill)
@ -120,6 +135,12 @@ void draw_point(int x, int y, float r, float *color)
draw_circle(x, y, r, r, color, 0); draw_circle(x, y, r, r, color, 0);
} }
void draw_points(struct cpVect *points, int n, float size, float *color)
{
for (int i = 0; i < n; i++)
draw_point(points[i].x, points[i].y, size, color);
}
void draw_poly(float *points, int n, float *color) void draw_poly(float *points, int n, float *color)
{ {
shader_use(rectShader); shader_use(rectShader);
@ -138,6 +159,17 @@ void draw_poly(float *points, int n, float *color)
glDrawArrays(GL_LINE_LOOP, 0, n); glDrawArrays(GL_LINE_LOOP, 0, n);
} }
void draw_polyvec(cpVect *points, int n, float *color)
{
float drawvec[n*2];
for (int i = 0; i < n; i++) {
drawvec[i*2] = points[i].x;
drawvec[i*2+1] = points[i].y;
}
draw_poly(drawvec, n, color);
}
void debugdraw_flush() void debugdraw_flush()
{ {

View file

@ -1,15 +1,19 @@
#ifndef DEBUGDRAW_H #ifndef DEBUGDRAW_H
#define DEBUGDRAW_H #define DEBUGDRAW_H
struct cpVect;
void debugdraw_init(); void debugdraw_init();
void draw_line(int x1, int y1, int x2, int y2, float *color); void draw_line(int x1, int y1, int x2, int y2, float *color);
void draw_edge(float *points, int n, float *color); void draw_edge(struct cpVect *points, int n, float *color);
void draw_points(struct cpVect *points, int n, float size, float *color);
void draw_circle(int x, int y, float radius, int pixels, float *color, int fill); void draw_circle(int x, int y, float radius, int pixels, float *color, int fill);
void draw_grid(int width, int span); void draw_grid(int width, int span);
void draw_rect(int x, int y, int w, int h, float *color); void draw_rect(int x, int y, int w, int h, float *color);
void draw_point(int x, int y, float r, float *color); void draw_point(int x, int y, float r, float *color);
void draw_poly(float *points, int n, float *color); void draw_poly(float *points, int n, float *color);
void debugdraw_flush(); /* This is called once per frame to draw all queued elements */ void debugdraw_flush(); /* This is called once per frame to draw all queued elements */

View file

@ -64,5 +64,5 @@ void engine_init()
phys2d_init(); phys2d_init();
YughInfo("Starting sound ..."); YughInfo("Starting sound ...");
sound_init(); //sound_init();
} }

View file

@ -21,6 +21,12 @@
#include "music.h" #include "music.h"
#include "level.h" #include "level.h"
void duk_dump_stack(duk_context *duk)
{
duk_push_context_dump(duk);
YughInfo("DUK STACK\n%s", duk_to_string(duk, -1));
}
struct color duk2color(duk_context *duk, int p) struct color duk2color(duk_context *duk, int p)
{ {
struct color color; struct color color;
@ -37,6 +43,8 @@ struct color duk2color(duk_context *duk, int p)
cpVect duk2vec2(duk_context *duk, int p) { cpVect duk2vec2(duk_context *duk, int p) {
cpVect pos; cpVect pos;
if (p < 0) p = duk_get_top_index(duk) + p + 1;
duk_get_prop_index(duk, p, 0); duk_get_prop_index(duk, p, 0);
pos.x = duk_to_number(duk, -1); pos.x = duk_to_number(duk, -1);
duk_get_prop_index(duk, p, 1); duk_get_prop_index(duk, p, 1);
@ -125,7 +133,6 @@ duk_ret_t duk_cmd(duk_context *duk) {
case 0: case 0:
duk_push_int(duk, script_dofile(duk_to_string(duk, 1))); duk_push_int(duk, script_dofile(duk_to_string(duk, 1)));
return 1; return 1;
break;
case 1: case 1:
set_pawn(duk_get_heapptr(duk, 1)); set_pawn(duk_get_heapptr(duk, 1));
@ -270,12 +277,21 @@ duk_ret_t duk_cmd(duk_context *duk) {
case 36: case 36:
id2go(duk_to_int(duk, 1))->scale = duk_to_number(duk, 2); id2go(duk_to_int(duk, 1))->scale = duk_to_number(duk, 2);
cpSpaceReindexShapesForBody(space, id2go(duk_to_int(duk, 1))->body);
return 0; return 0;
case 37: case 37:
if (!id2sprite(duk_to_int(duk, 1))) return 0; if (!id2sprite(duk_to_int(duk, 1))) return 0;
vec2float(duk2vec2(duk, 2), id2sprite(duk_to_int(duk, 1))->pos); vec2float(duk2vec2(duk, 2), id2sprite(duk_to_int(duk, 1))->pos);
break; break;
case 38:
duk_push_string(duk, slurp_text(duk_to_string(duk, 1)));
return 1;
case 39:
duk_push_int(duk, slurp_write(duk_to_string(duk, 1), duk_to_string(duk, 2)));
return 1;
} }
return 0; return 0;
@ -331,6 +347,7 @@ duk_ret_t duk_sys_cmd(duk_context *duk) {
case 1: case 1:
sim_start(); sim_start();
cpSpaceReindexStatic(space);
break; break;
case 2: case 2:
@ -410,7 +427,6 @@ duk_ret_t duk_set_body(duk_context *duk) {
switch (cmd) { switch (cmd) {
case 0: case 0:
gameobject_setangle(go, duk_to_number(duk, 2)); gameobject_setangle(go, duk_to_number(duk, 2));
cpSpaceReindexShapesForBody(space, go->body);
break; break;
case 1: case 1:
@ -419,7 +435,6 @@ duk_ret_t duk_set_body(duk_context *duk) {
case 2: case 2:
cpBodySetPosition(go->body, duk2vec2(duk, 2)); cpBodySetPosition(go->body, duk2vec2(duk, 2));
cpSpaceReindexShapesForBody(space, go->body);
break; break;
case 3: case 3:
@ -452,6 +467,8 @@ duk_ret_t duk_set_body(duk_context *duk) {
} }
cpSpaceReindexShapesForBody(space, go->body);
return 0; return 0;
} }
@ -543,20 +560,26 @@ duk_ret_t duk_cmd_box2d(duk_context *duk)
{ {
int cmd = duk_to_int(duk, 0); int cmd = duk_to_int(duk, 0);
struct phys2d_box *box = duk_to_pointer(duk, 1); struct phys2d_box *box = duk_to_pointer(duk, 1);
cpVect arg = duk2vec2(duk, 2); cpVect arg;
if (!box) return 0; if (!box) return 0;
switch(cmd) { switch(cmd) {
case 0: case 0:
arg = duk2vec2(duk, 2);
box->w = arg.x; box->w = arg.x;
box->h = arg.y; box->h = arg.y;
break; break;
case 1: case 1:
arg = duk2vec2(duk, 2);
box->offset[0] = arg.x; box->offset[0] = arg.x;
box->offset[1] = arg.y; box->offset[1] = arg.y;
break; break;
case 2:
box->rotation = duk_to_number(duk, 2);
break;
} }
phys2d_applybox(box); phys2d_applybox(box);
@ -603,6 +626,54 @@ duk_ret_t duk_cmd_circle2d(duk_context *duk)
return 0; return 0;
} }
duk_ret_t duk_make_poly2d(duk_context *duk)
{
int go = duk_to_int(duk, 0);
struct phys2d_poly *poly = Make2DPoly(go);
YughInfo("Making polygon.");
return 0;
}
duk_ret_t duk_cmd_poly2d(duk_context *duk)
{
}
duk_ret_t duk_make_edge2d(duk_context *duk)
{
int go = duk_to_int(duk, 0);
struct phys2d_edge *edge = Make2DEdge(go);
int arridx = 1;
int n = duk_get_length(duk, arridx);
cpVect points[n];
for (int i = 0; i < n; i++) {
duk_get_prop_index(duk, arridx, i);
points[i] = duk2vec2(duk, -1);
phys2d_edgeaddvert(edge);
phys2d_edge_setvert(edge, i, points[i]);
}
int idx = duk_push_object(duk);
duk_push_pointer(duk, &edge->shape);
duk_put_prop_string(duk, idx, "id");
duk_push_pointer(duk, edge);
duk_put_prop_string(duk, idx, "shape");
return 1;
}
duk_ret_t duk_cmd_edge2d(duk_context *duk)
{
}
/* These are anims for controlling properties on an object */ /* These are anims for controlling properties on an object */
duk_ret_t duk_anim(duk_context *duk) { duk_ret_t duk_anim(duk_context *duk) {
void *prop = duk_get_heapptr(duk, 0); void *prop = duk_get_heapptr(duk, 0);
@ -663,6 +734,10 @@ void ffi_load()
DUK_FUNC(cmd_box2d, DUK_VARARGS); DUK_FUNC(cmd_box2d, DUK_VARARGS);
DUK_FUNC(make_circle2d, 3); DUK_FUNC(make_circle2d, 3);
DUK_FUNC(cmd_circle2d, DUK_VARARGS); DUK_FUNC(cmd_circle2d, DUK_VARARGS);
DUK_FUNC(make_poly2d, 2);
DUK_FUNC(cmd_poly2d, DUK_VARARGS);
DUK_FUNC(make_edge2d, 3);
DUK_FUNC(cmd_edge2d, DUK_VARARGS);
DUK_FUNC(make_timer, 3); DUK_FUNC(make_timer, 3);
DUK_FUNC(cmd, DUK_VARARGS); DUK_FUNC(cmd, DUK_VARARGS);

View file

@ -54,6 +54,16 @@ unsigned char *slurp_text(const char *filename) {
return buf; return buf;
} }
int slurp_write(const char *txt, const char *filename)
{
FILE *f = fopen(filename, "w");
if (!f) return 1;
fputs(txt, f);
fclose(f);
return 0;
}
void font_init(struct shader *textshader) { void font_init(struct shader *textshader) {
shader = textshader; shader = textshader;

View file

@ -34,4 +34,6 @@ void renderText(const char *text, mfloat_t pos[2], float scale, mfloat_t color[3
unsigned char *slurp_file(const char *filename); unsigned char *slurp_file(const char *filename);
unsigned char *slurp_text(const char *filename); unsigned char *slurp_text(const char *filename);
int slurp_write(const char *txt, const char *filename);
#endif #endif

View file

@ -6,6 +6,8 @@
#include <string.h> #include <string.h>
#include "log.h" #include "log.h"
#include <assert.h>
static struct bus bus[256]; static struct bus bus[256];
static int first = 0; /* First bus available */ static int first = 0; /* First bus available */
//static struct bus *first_on = NULL; //static struct bus *first_on = NULL;
@ -35,10 +37,8 @@ void mixer_init() {
} }
struct bus *first_free_bus(struct dsp_filter in) { struct bus *first_free_bus(struct dsp_filter in) {
if (!initted) { if (!initted) return;
YughError("Tried to use a mixing bus without calling mixer_init()."); assert(initted);
return NULL;
}
if (first == -1) return NULL; if (first == -1) return NULL;
int ret = first; int ret = first;