From 64a82c2a26b3f3a626f7f4164e0d02f727fec487 Mon Sep 17 00:00:00 2001 From: Cameron Reikes Date: Thu, 20 Oct 2022 07:02:43 -0700 Subject: [PATCH] Switch to chipmunk --- .gitmodules | 3 + .vscode/settings.json | 7 +- build_debug.bat | 15 +- flight.exp | Bin 0 -> 50719 bytes flight.lib | Bin 0 -> 83642 bytes gamestate.c | 398 +++++++++++++++++++++--------------------- main.c | 43 ++--- server.c | 51 +++--- thirdparty/Chipmunk2D | 1 + tooling.ahk | 4 +- types.h | 66 ++++--- 11 files changed, 312 insertions(+), 276 deletions(-) create mode 100644 flight.exp create mode 100644 flight.lib create mode 160000 thirdparty/Chipmunk2D diff --git a/.gitmodules b/.gitmodules index 69b0692..5d1c17e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "thirdparty/enet"] path = thirdparty/enet url = https://github.com/lsalzman/enet.git +[submodule "thirdparty/Chipmunk2D"] + path = thirdparty/Chipmunk2D + url = https://github.com/slembcke/Chipmunk2D.git diff --git a/.vscode/settings.json b/.vscode/settings.json index fc2cb77..bcaafff 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -31,6 +31,11 @@ "types.h": "c", "cmath": "c", "math.h": "c", - "corecrt_math.h": "c" + "corecrt_math.h": "c", + "cppolyline.h": "c", + "chipmunk_private.h": "c", + "chipmunk.h": "c", + "cpbody.h": "c", + "chipmunk_structs.h": "c" } } \ No newline at end of file diff --git a/build_debug.bat b/build_debug.bat index a7fd93a..13f8efb 100644 --- a/build_debug.bat +++ b/build_debug.bat @@ -1,11 +1,20 @@ @echo off -@REM what all the flags mean: https://learn.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-by-category?view=msvc-170 +@REM what all the compile flags mean: https://learn.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-by-category?view=msvc-170 WHERE sokol-shdc.exe IF %ERRORLEVEL% NEQ 0 ECHO ERROR download sokol-shdc from https://github.com/floooh/sokol-tools-bin/blob/master/bin/win32/sokol-shdc.exe and put it in this folder @REM example of how to compile shaders: sokol-shdc.exe --input triangle.glsl --output triangle.gen.h --slang glsl330:hlsl5:metal_macos -cl /MP /Zi /Fd"flight.pdb" /I"thirdparty" /Fe"flight" /I"thirdparty\enet\include" main.c gamestate.c server.c debugdraw.c^ - thirdparty\enet\callbacks.c thirdparty\enet\compress.c thirdparty\enet\host.c thirdparty\enet\list.c thirdparty\enet\packet.c thirdparty\enet\peer.c thirdparty\enet\protocol.c thirdparty\enet\win32.c Ws2_32.lib winmm.lib \ No newline at end of file +setlocal enabledelayedexpansion enableextensions +pushd thirdparty\Chipmunk2D\src + set MUNKSRC= + for %%x in (*.c) do set MUNKSRC=!MUNKSRC! thirdparty\Chipmunk2D\src\%%x +popd + +cl /MP /Zi /Fd"flight.pdb" /Fe"flight"^ + /I"thirdparty" /I"thirdparty\enet\include" /I"thirdparty\Chipmunk2D\include\chipmunk" /I"thirdparty\Chipmunk2D\include"^ + main.c gamestate.c server.c debugdraw.c^ + thirdparty\enet\callbacks.c thirdparty\enet\compress.c thirdparty\enet\host.c thirdparty\enet\list.c thirdparty\enet\packet.c thirdparty\enet\peer.c thirdparty\enet\protocol.c thirdparty\enet\win32.c Ws2_32.lib winmm.lib^ + %MUNKSRC% \ No newline at end of file diff --git a/flight.exp b/flight.exp new file mode 100644 index 0000000000000000000000000000000000000000..2d10d360ccca4081156d4405a8a8b9d3be3402ec GIT binary patch literal 50719 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 literal 0 HcmV?d00001 diff --git a/flight.lib b/flight.lib new file mode 100644 index 0000000000000000000000000000000000000000..90c74e52b688e15793267b9e9b3891ef11facad2 GIT binary patch literal 83642 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 literal 0 HcmV?d00001 diff --git a/gamestate.c b/gamestate.c index 0f2dc6e..5881f86 100644 --- a/gamestate.c +++ b/gamestate.c @@ -1,7 +1,7 @@ +#include #include "types.h" -#include // malloc -#include +#include // assert logging void __assert(bool cond, const char *file, int line, const char *cond_string) { @@ -17,251 +17,257 @@ void __assert(bool cond, const char *file, int line, const char *cond_string) // super try not to depend on external libraries like enet or sokol to keep build process simple, // gamestate its own portable submodule. If need to link to other stuff document here: -// - debug +// - debug.c for debug drawing +// - chipmunk -static void integrate_acceleration(struct Body *body, float dt) +void initialize(struct GameState *gs) { - // position + gs->space = cpSpaceNew(); +} +void destroy(struct GameState *gs) +{ + for (int i = 0; i < MAX_PLAYERS; i++) { - V2 current = body->position; - body->position = V2add(body->position, V2sub(current, body->old_position)); - body->position = V2add(body->position, V2scale(body->acceleration, dt * dt)); - body->old_position = current; + box_destroy(&gs->players[i].box); } - - // rotation + for (int i = 0; i < gs->num_boxes; i++) { - float current = body->rotation; - body->rotation = body->rotation + (current - body->old_rotation); - body->rotation = body->rotation + body->angular_acceleration * dt * dt; - body->old_rotation = current; + box_destroy(&gs->boxes[i]); } + gs->num_boxes = 0; + cpSpaceDestroy(gs->space); + gs->space = NULL; } -struct ProcessBody +struct Box box_new(struct GameState *gs, V2 pos) { - V2 vertices[4]; - struct Body *body; -}; + assert(gs->space != NULL); + float halfbox = BOX_SIZE / 2.0f; + cpBody *body = cpSpaceAddBody(gs->space, cpBodyNew(BOX_MASS, cpMomentForBox(BOX_MASS, BOX_SIZE, BOX_SIZE))); + cpShape *shape = cpBoxShapeNew(body, BOX_SIZE, BOX_SIZE, 0.0f); + cpSpaceAddShape(gs->space, shape); + cpBodySetPosition(body, cpv(pos.x, pos.y)); + + return (struct Box){ + .body = body, + .shape = shape, + }; +} -struct ProcessBody make_process_body(struct Body *from) +void box_destroy(struct Box *box) { - float halfbox = BOX_SIZE / 2.0f; - struct ProcessBody to_return = - { - .vertices = { - // important that the first one is the upper right, used to deduce rotation from vertex position - // @Robust instead of array of vertices have type? like struct with upper_right upper_left etc - V2add(from->position, V2rotate((V2){.x = halfbox, .y = -halfbox}, from->rotation)), // upper right - V2add(from->position, V2rotate((V2){.x = halfbox, .y = halfbox}, from->rotation)), // bottom right - V2add(from->position, V2rotate((V2){.x = -halfbox, .y = halfbox}, from->rotation)), // lower left - V2add(from->position, V2rotate((V2){.x = -halfbox, .y = -halfbox}, from->rotation)), // upper left - }, - .body = from, - }; - return to_return; + cpShapeFree(box->shape); + cpBodyFree(box->body); + box->shape = NULL; + box->body = NULL; } -static void project(struct ProcessBody *from, V2 axis, float *min, float *max) +static V2 cp_to_v2(cpVect v) { - float DotP = V2dot(axis, from->vertices[0]); + return (V2){.x = v.x, .y = v.y}; +} - // Set the minimum and maximum values to the projection of the first vertex - *min = DotP; - *max = DotP; +static cpVect v2_to_cp(V2 v) +{ + return cpv(v.x, v.y); +} - for (int I = 1; I < 4; I++) - { - // Project the rest of the vertices onto the axis and extend - // the interval to the left/right if necessary - DotP = V2dot(axis, from->vertices[I]); +V2 box_pos(struct Box box) +{ + return cp_to_v2(cpBodyGetPosition(box.body)); +} +V2 box_vel(struct Box box) +{ + return cp_to_v2(cpBodyGetVelocity(box.body)); +} +float box_rotation(struct Box box) +{ + return cpBodyGetAngle(box.body); +} +float box_angular_velocity(struct Box box) +{ + return cpBodyGetAngularVelocity(box.body); +} - *min = fmin(DotP, *min); - *max = fmax(DotP, *max); +#define memwrite(out, variable) \ + for (char b = 0; b < sizeof(variable); b++) \ + { \ + **out = ((char *)&variable)[b]; \ + *out += 1; \ } + +#define memread(in, variable_pointer) \ + for (char b = 0; b < sizeof(*variable_pointer); b++) \ + { \ + ((char *)variable_pointer)[b] = **in; \ + *in += 1; \ + } + +void ser_float(char **out, float f) +{ + memwrite(out, f); +} + +void des_float(char **in, float *f) +{ + memread(in, f); +} + +void ser_int(char **out, int i) +{ + memwrite(out, i); } -static float interval_distance(float min_a, float max_a, float min_b, float max_b) +void des_int(char **in, int *i) { - if (min_a < min_b) - return min_b - max_a; - else - return min_a - max_b; + memread(in, i); } -static void move_vertices(V2 *vertices, int num, V2 shift) +void ser_bool(char **out, bool b) { - for (int i = 0; i < num; i++) + **out = (char)b; + *out += 1; +} + +void des_bool(char **in, bool *b) +{ + *b = (bool)**in; + *in += 1; +} + +void ser_V2(char **out, V2 v) +{ + ser_float(out, v.x); + ser_float(out, v.y); +} + +void des_V2(char **in, V2 *v) +{ + des_float(in, &v->x); + des_float(in, &v->y); +} + +void ser_box(char **out, struct Box *b) +{ + // box must not be null, dummy! + assert(b->body != NULL); + ser_V2(out, box_pos(*b)); + ser_V2(out, box_vel(*b)); + ser_float(out, box_rotation(*b)); + ser_float(out, box_angular_velocity(*b)); +} + +// takes gamestate as argument to place box in the gamestates space +void des_box(char **in, struct Box *b, struct GameState *gs) +{ + assert(b->body == NULL); // destroy the box before deserializing into it + V2 pos = {0}; + V2 vel = {0}; + float rot = 0.0f; + float angular_vel = 0.0f; + + des_V2(in, &pos); + des_V2(in, &vel); + des_float(in, &rot); + des_float(in, &angular_vel); + + *b = box_new(gs, pos); + cpBodySetVelocity(b->body, v2_to_cp(vel)); + cpBodySetAngle(b->body, rot); + cpBodySetAngularVelocity(b->body, angular_vel); +} + +void ser_player(char **out, struct Player *p) +{ + ser_bool(out, p->connected); + if (p->connected) { - vertices[i] = V2add(vertices[i], shift); + ser_box(out, &p->box); + ser_V2(out, p->input); } } -void process(struct GameState *gs, float dt) +void des_player(char **in, struct Player *p, struct GameState *gs) { - // process input - int num_bodies = gs->num_boxes; - for (int i = 0; i < MAX_PLAYERS; i++) + des_bool(in, &p->connected); + if (p->connected) { - struct Player *p = &gs->players[i]; - if (!p->connected) - continue; - p->body.acceleration = V2scale(p->input, 5.0f); - p->body.angular_acceleration = p->input.x * 10.0f; - num_bodies += 1; + des_box(in, &p->box, gs); + des_V2(in, &p->input); } +} - // @Robust do this without malloc +// @Robust really think about if <= makes more sense than < here... +#define LEN_CHECK() assert(bytes - original_bytes <= max_len) - struct ProcessBody *bodies = malloc(sizeof *bodies * num_bodies); - int cur_body_index = 0; +void into_bytes(struct ServerToClient *msg, char *bytes, int *out_len, int max_len) +{ + assert(msg->cur_gs != NULL); + assert(msg != NULL); + struct GameState *gs = msg->cur_gs; + char *original_bytes = bytes; + + ser_int(&bytes, msg->your_player); for (int i = 0; i < MAX_PLAYERS; i++) { - struct Player *p = &gs->players[i]; - if (!p->connected) - continue; - integrate_acceleration(&p->body, dt); - bodies[cur_body_index] = make_process_body(&p->body); - cur_body_index++; + ser_player(&bytes, &gs->players[i]); + LEN_CHECK(); } + // @Robust invalid message on num boxes bigger than max boxes + ser_int(&bytes, gs->num_boxes); + LEN_CHECK(); + for (int i = 0; i < gs->num_boxes; i++) { - integrate_acceleration(&gs->boxes[i].body, dt); - bodies[cur_body_index] = make_process_body(&gs->boxes[i].body); - cur_body_index++; + ser_box(&bytes, &gs->boxes[i]); + LEN_CHECK(); } - assert(cur_body_index == num_bodies); + *out_len = bytes - original_bytes; +} - // Collision - // @Robust handle when bodies are overlapping (even perfectly) - for (int i = 0; i < num_bodies; i++) - { - for (int ii = 0; ii < num_bodies; ii++) - { - if (ii == i) - continue; - struct ProcessBody *from = &bodies[i]; - struct ProcessBody *to = &bodies[ii]; - dbg_line(from->body->position, to->body->position); - - float MinDistance = 10000.0f; - - struct Edge - { - struct ProcessBody *parent; - V2 *from; - V2 *to; - }; - - struct ProcessBody *bodies[2] = {from, to}; - bool was_collision = false; - V2 normal = {0}; - struct Edge edge = {0}; - for (int body_i = 0; body_i < 2; body_i++) - { - struct ProcessBody *body = bodies[body_i]; - for (int edge_from_i = 0; edge_from_i < 3; edge_from_i++) - { - int edge_to_i = edge_from_i + 1; - V2 *edge_from = &body->vertices[edge_from_i]; - V2 *edge_to = &body->vertices[edge_to_i]; - - // normal vector of edge - V2 axis = (V2){ - .x = edge_from->y - edge_to->y, - .y = edge_to->x - edge_from->x, - }; - axis = V2normalize(axis); - - float min_from, min_to, max_from, max_to = 0.0f; - project(from, axis, &min_from, &max_from); - project(to, axis, &min_to, &max_to); - - float distance = interval_distance(min_from, min_to, max_from, max_to); - - if (distance > 0.0f) - break; - else if (fabsf(distance) < MinDistance) - { - MinDistance = fabsf(distance); - was_collision = true; - normal = axis; - edge = (struct Edge){ - .parent = &body, - .from = edge_from, - .to = edge_to, - }; - } - } - } - float depth = MinDistance; - if (was_collision) - { - float intersection_depth = from_interval[1] - to_interval[0]; - - move_vertices(from->vertices, 4, V2scale(axis, intersection_depth * -0.5f)); - move_vertices(to->vertices, 4, V2scale(axis, intersection_depth * 0.5f)); - } - } - } +void from_bytes(struct ServerToClient *msg, char *bytes, int max_len) +{ + struct GameState *gs = msg->cur_gs; - // Wall - if (true) + char *original_bytes = bytes; + // destroy and free all chipmunk + destroy(gs); + initialize(gs); + + des_int(&bytes, &msg->your_player); + LEN_CHECK(); + + for (int i = 0; i < MAX_PLAYERS; i++) { - for (int i = 0; i < num_bodies; i++) - { - for (int v_i = 0; v_i < 4; v_i++) - { - V2 *vert = &bodies[i].vertices[v_i]; - if (vert->x > 2.0f) - { - vert->x = 2.0f; - } - } - } + des_player(&bytes, &gs->players[i], gs); + LEN_CHECK(); } - // Correct for differences in vertex position - const int edge_update_iters = 3; - for (int iter = 0; iter < edge_update_iters; iter++) + des_int(&bytes, &gs->num_boxes); + LEN_CHECK(); + + for (int i = 0; i < gs->num_boxes; i++) { - for (int i = 0; i < num_bodies; i++) - { - for (int v_i = 0; v_i < 3; v_i++) - { - int other_v_i = v_i + 1; - V2 *from = &bodies[i].vertices[v_i]; - V2 *to = &bodies[i].vertices[other_v_i]; - - V2 line = V2sub(*to, *from); - float len = V2length(line); - float diff = len - BOX_SIZE; - - line = V2normalize(line); - - *from = V2add(*from, V2scale(line, diff * 0.5f)); - *to = V2sub(*to, V2scale(line, diff * 0.5f)); - } - } + des_box(&bytes, &gs->boxes[i], gs); + LEN_CHECK(); } +} - // Reupdate the positions of the bodies based on how the vertices changed - for (int i = 0; i < num_bodies; i++) +void process(struct GameState *gs, float dt) +{ + assert(gs->space != NULL); + + // process input + for (int i = 0; i < MAX_PLAYERS; i++) { - float upper_right_angle = V2angle(V2sub(bodies[i].vertices[0], bodies[i].body->position)); - bodies[i].body->rotation = upper_right_angle - (PI / 4.0f); - - V2 avg = {0}; - for (int v_i = 0; v_i < 4; v_i++) - { - avg = V2add(avg, bodies[i].vertices[v_i]); - } - avg = V2scale(avg, 1.0f / 4.0f); - bodies[i].body->position = avg; + struct Player *p = &gs->players[i]; + if (!p->connected) + continue; + cpBodyApplyForceAtWorldPoint(p->box.body, v2_to_cp(V2scale(p->input, 5.0f)), v2_to_cp(box_pos(p->box))); } - free(bodies); + cpSpaceStep(gs->space, dt); } \ No newline at end of file diff --git a/main.c b/main.c index a58e1c4..443ab17 100644 --- a/main.c +++ b/main.c @@ -26,6 +26,8 @@ void init(void) { // @BeforeShip make all fprintf into logging to file, warning dialog boxes on failure instead of exit(-1), replace the macros in sokol with this as well, like assert + initialize(&gs); + sg_desc sgdesc = {.context = sapp_sgcontext()}; sg_setup(&sgdesc); if (!sg_isvalid()) @@ -114,17 +116,11 @@ static void frame(void) // and other validation instead of just casting to a struct // "Alignment of structure members can be different even among different compilers on the same platform, let alone different platforms." // ^^ need serialization strategy that accounts for this if multiple platforms is happening https://stackoverflow.com/questions/28455163/how-can-i-portably-send-a-c-struct-through-a-network-socket - struct ServerToClient msg; - if (event.packet->dataLength != sizeof(msg)) - { - Log("Unknown packet size: %zd\n", event.packet->dataLength); - } - else - { - memcpy(&msg, event.packet->data, sizeof(msg)); - myplayer = msg.your_player; - gs = msg.cur_gs; - } + struct ServerToClient msg = { + .cur_gs = &gs, + }; + // @Robust maximum acceptable message size? + from_bytes(&msg, event.packet->data, event.packet->dataLength); enet_packet_destroy(event.packet); break; case ENET_EVENT_TYPE_DISCONNECT: @@ -179,7 +175,8 @@ static void frame(void) // camera go to player if (myplayer != -1) { - sgp_translate(-gs.players[myplayer].body.position.x, -gs.players[myplayer].body.position.y); + V2 pos = box_pos(gs.players[myplayer].box); + sgp_translate(-pos.x, -pos.y); } sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f); @@ -204,14 +201,14 @@ static void frame(void) continue; sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f); sgp_push_transform(); - sgp_rotate_at(p->body.rotation, p->body.position.x, p->body.position.y); - sgp_draw_filled_rect(p->body.position.x - halfbox, p->body.position.y - halfbox, BOX_SIZE, BOX_SIZE); + sgp_rotate_at(box_rotation(p->box), box_pos(p->box).x, box_pos(p->box).y); + sgp_draw_filled_rect(box_pos(p->box).x - halfbox, box_pos(p->box).y - halfbox, BOX_SIZE, BOX_SIZE); sgp_pop_transform(); sgp_set_color(1.0f, 0.0f, 0.0f, 1.0f); - V2 vel = (V2scale(V2sub(p->body.position, p->body.old_position), 60.0f)); - V2 to = V2add(p->body.position, vel); - sgp_draw_line(p->body.position.x, p->body.position.y, to.x, to.y); + V2 vel = box_vel(p->box); + V2 to = V2add(box_pos(p->box), vel); + sgp_draw_line(box_pos(p->box).x, box_pos(p->box).y, to.x, to.y); } // boxes @@ -219,12 +216,15 @@ static void frame(void) for (int i = 0; i < gs.num_boxes; i++) { sgp_set_color(0.5f, 0.5f, 0.5f, 1.0f); - sgp_draw_filled_rect(gs.boxes[i].body.position.x - halfbox, gs.boxes[i].body.position.y - halfbox, BOX_SIZE, BOX_SIZE); + sgp_push_transform(); + sgp_rotate_at(box_rotation(gs.boxes[i]), box_pos(gs.boxes[i]).x, box_pos(gs.boxes[i]).y); + sgp_draw_filled_rect(box_pos(gs.boxes[i]).x - halfbox, box_pos(gs.boxes[i]).y - halfbox, BOX_SIZE, BOX_SIZE); + sgp_pop_transform(); sgp_set_color(1.0f, 0.0f, 0.0f, 1.0f); - V2 vel = (V2scale(V2sub(gs.boxes[i].body.position, gs.boxes[i].body.old_position), 60.0f)); - V2 to = V2add(gs.boxes[i].body.position, vel); - sgp_draw_line(gs.boxes[i].body.position.x, gs.boxes[i].body.position.y, to.x, to.y); + V2 vel = box_vel(gs.boxes[i]); + V2 to = V2add(box_pos(gs.boxes[i]), vel); + sgp_draw_line(box_pos(gs.boxes[i]).x, box_pos(gs.boxes[i]).y, to.x, to.y); } } @@ -247,6 +247,7 @@ static void frame(void) void cleanup(void) { + destroy(&gs); sgp_shutdown(); sg_shutdown(); enet_deinitialize(); diff --git a/server.c b/server.c index eca85f0..f29fb3a 100644 --- a/server.c +++ b/server.c @@ -14,31 +14,20 @@ void server(void *data) stm_setup(); struct GameState gs = {0}; + initialize(&gs); // two boxes stacked on top - if (false) + if (true) { - gs.boxes[0] = (struct Box){ - .body = (struct Body){ - .position = (P2){.x = 0.75f, .y = 0.0}}, - }; - gs.boxes[0].body.old_position = gs.boxes[0].body.position; - gs.boxes[1] = (struct Box){ - .body = (struct Body){ - .position = (P2){.x = 0.75f, .y = 0.5f}}, - }; - gs.boxes[1].body.old_position = gs.boxes[1].body.position; + gs.boxes[0] = box_new(&gs, (V2){.x = 0.75f, .y = 0.0}); + gs.boxes[1] = box_new(&gs, (V2){.x = 0.75f, .y = 0.5f}); gs.num_boxes = 2; } // one box - if (true) + if (false) { - gs.boxes[0] = (struct Box){ - .body = (struct Body){ - .position = (P2){.x = 0.75f, .y = 0.0}}, - }; - gs.boxes[0].body.old_position = gs.boxes[0].body.position; + gs.boxes[0] = box_new(&gs, (V2){.x = 0.75f, .y = 0.0}); gs.num_boxes = 1; } @@ -107,11 +96,10 @@ void server(void *data) else { event.peer->data = (void *)player_slot; - gs.players[player_slot] = (struct Player){.body.position = (V2){ - .x = 0.0f, - .y = 1.0f * (float)player_slot, - }}; - gs.players[player_slot].body.old_position = gs.players[player_slot].body.position; + gs.players[player_slot].box = box_new(&gs, (V2){ + .x = 0.0f, + .y = 1.0f * (float)player_slot, + }); gs.players[player_slot].connected = true; } @@ -140,8 +128,10 @@ void server(void *data) break; case ENET_EVENT_TYPE_DISCONNECT: - Log("%" PRId64 " disconnected.\n", (int64_t)event.peer->data); - gs.players[(int64_t)event.peer->data].connected = false; + int player_index = (int64_t)event.peer->data; + Log("%" PRId64 " disconnected player index %d.\n", (int64_t)event.peer->data, player_index); + gs.players[player_index].connected = false; + box_destroy(&gs.players[player_index].box); event.peer->data = NULL; } } @@ -149,13 +139,15 @@ void server(void *data) total_time += (float)stm_sec(stm_diff(stm_now(), last_processed_time)); last_processed_time = stm_now(); - // @Robost if can't process quick enough will be stuck being lagged behind, think of a solution for this... + // @Robost @BeforeShip if can't process quick enough will be stuck being lagged behind, think of a solution for this... while (total_time > TIMESTEP) { process(&gs, TIMESTEP); total_time -= TIMESTEP; } +#define MAX_BYTES_SIZE 2048 * 2 + static char bytes_buffer[MAX_BYTES_SIZE] = {0}; for (int i = 0; i < server->peerCount; i++) { // @Speed don't recreate the packet for every peer, gets expensive copying gamestate over and over again @@ -164,13 +156,18 @@ void server(void *data) continue; } struct ServerToClient to_send; - to_send.cur_gs = gs; + to_send.cur_gs = &gs; to_send.your_player = (int)(int64_t)server->peers[i].data; - ENetPacket *gamestate_packet = enet_packet_create((void *)&to_send, sizeof(struct ServerToClient), ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT); + + int len = 0; + into_bytes(&to_send, bytes_buffer, &len, MAX_BYTES_SIZE); + + ENetPacket *gamestate_packet = enet_packet_create((void *)bytes_buffer, len, ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT); enet_peer_send(&server->peers[i], 0, gamestate_packet); } } + destroy(&gs); enet_host_destroy(server); enet_deinitialize(); } \ No newline at end of file diff --git a/thirdparty/Chipmunk2D b/thirdparty/Chipmunk2D new file mode 160000 index 0000000..352d13c --- /dev/null +++ b/thirdparty/Chipmunk2D @@ -0,0 +1 @@ +Subproject commit 352d13cf6574a63a129ce40e011eec2e248cbe34 diff --git a/tooling.ahk b/tooling.ahk index a4b0255..6a991a1 100644 --- a/tooling.ahk +++ b/tooling.ahk @@ -13,7 +13,7 @@ WinKill, Flight WinActivate, flightbuild If WinActive("flightbuild") { - Send, build_debug.bat && flight.exe --host{Enter} + Send, cd C:\Users\Cameron\Documents\flight{Enter} build_debug.bat && flight.exe --host{Enter} } return @@ -26,6 +26,6 @@ WinKill, Flight WinActivate, flightbuild If WinActive("flightbuild") { - Send, build_debug.bat && START /B flight.exe && flight.exe --host{Enter} + Send, cd C:\Users\Cameron\Documents\flight{Enter} build_debug.bat && START /B flight.exe && flight.exe --host{Enter} } return \ No newline at end of file diff --git a/types.h b/types.h index c349095..85b630b 100644 --- a/types.h +++ b/types.h @@ -1,5 +1,10 @@ #pragma once +#define MAX_PLAYERS 4 +#define BOX_SIZE 0.5f +#define MAX_BOXES 128 +#define BOX_MASS 1.0f + // @Robust remove this include somehow, needed for sqrt and cos #include @@ -15,6 +20,16 @@ typedef sgp_vec2 sgp_point; #endif +#ifndef CHIPMUNK_H +typedef void cpSpace; +typedef void cpBody; +typedef void cpShape; + +extern void cpShapeFree(cpShape *); +extern void cpBodyFree(cpBody *); +extern void cpSpaceFree(cpSpace *); +#endif + #include #ifndef _STDBOOL @@ -31,43 +46,30 @@ typedef sgp_point P2; #define Log(...) \ fprintf(stdout, "%s:%d | ", __FILE__, __LINE__); \ fprintf(stdout, __VA_ARGS__) -#define MAX_BOXES 32 -#define MAX_PLAYERS 4 -#define BOX_SIZE 0.5f -struct Body +struct Box { - P2 position; - P2 old_position; - - float rotation; - float old_rotation; - - V2 acceleration; - float angular_acceleration; -}; - -struct Player -{ - struct Body body; - bool connected; - V2 input; + cpBody *body; + cpShape *shape; }; +// gotta update the serialization functions when this changes struct GameState { - struct Player players[MAX_PLAYERS]; - - int num_boxes; - struct Box + cpSpace *space; + struct Player { - struct Body body; - } boxes[MAX_BOXES]; + struct Box box; + bool connected; + V2 input; + } players[MAX_PLAYERS]; + int num_boxes; + struct Box boxes[MAX_BOXES]; }; struct ServerToClient { - struct GameState cur_gs; + struct GameState *cur_gs; int your_player; }; @@ -80,7 +82,19 @@ struct ClientToServer void server(void *data); // gamestate +void initialize(struct GameState *gs); // must do this to place boxes into it and process +void destroy(struct GameState *gs); void process(struct GameState *gs, float dt); // does in place +void into_bytes(struct ServerToClient *gs, char *out_bytes, int *out_len, int max_len); +void from_bytes(struct ServerToClient *gs, char *bytes, int max_len); + +// box +struct Box box_new(struct GameState *gs, V2 pos); +void box_destroy(struct Box * box); +V2 box_pos(struct Box box); +V2 box_vel(struct Box box); +float box_rotation(struct Box box); +float box_angular_velocity(struct Box box); // debug draw void dbg_drawall();