Building and destruction of blocks

main
Cameron Murphy Reikes 2 years ago
parent f2ef6d8531
commit b61ec16309

@ -96,7 +96,7 @@ static cpBool on_damage(cpArbiter *arb, cpSpace *space, cpDataPointer userData)
float damage = V2length(cp_to_v2(cpArbiterTotalImpulse(arb))) * 0.25f; float damage = V2length(cp_to_v2(cpArbiterTotalImpulse(arb))) * 0.25f;
if (damage > 0.05f) if (damage > 0.05f)
{ {
Log("Collision with damage %f\n", damage); // Log("Collision with damage %f\n", damage);
getbox(a)->damage += damage; getbox(a)->damage += damage;
getbox(b)->damage += damage; getbox(b)->damage += damage;
} }
@ -139,9 +139,10 @@ void reset_player(struct Player *p)
} }
// box must be passed as a parameter as the box added to chipmunk uses this pointer in its // box must be passed as a parameter as the box added to chipmunk uses this pointer in its
// user data // user data. pos is in local coordinates
void box_new(struct Box *to_modify, struct GameState *gs, struct Grid *grid, V2 pos) void box_new(struct Box *to_modify, struct GameState *gs, struct Grid *grid, V2 pos)
{ {
*to_modify = (struct Box){0};
float halfbox = BOX_SIZE / 2.0f; float halfbox = BOX_SIZE / 2.0f;
cpBB box = cpBBNew(-halfbox + pos.x, -halfbox + pos.y, halfbox + pos.x, halfbox + pos.y); cpBB box = cpBBNew(-halfbox + pos.x, -halfbox + pos.y, halfbox + pos.x, halfbox + pos.y);
cpVect verts[4] = { cpVect verts[4] = {
@ -184,9 +185,14 @@ V2 grid_vel(struct Grid *grid)
{ {
return cp_to_v2(cpBodyGetVelocity(grid->body)); return cp_to_v2(cpBodyGetVelocity(grid->body));
} }
V2 grid_world_to_local(struct Grid *grid, V2 world)
{
return cp_to_v2(cpBodyWorldToLocal(grid->body, v2_to_cp(world)));
}
// returned snapped position is in world coordinates
V2 grid_snapped_box_pos(struct Grid *grid, V2 world) V2 grid_snapped_box_pos(struct Grid *grid, V2 world)
{ {
V2 local = cp_to_v2(cpBodyWorldToLocal(grid->body, v2_to_cp(world))); V2 local = grid_world_to_local(grid, world);
local.x /= BOX_SIZE; local.x /= BOX_SIZE;
local.y /= BOX_SIZE; local.y /= BOX_SIZE;
local.x = roundf(local.x); local.x = roundf(local.x);
@ -336,8 +342,14 @@ void ser_player(char **out, struct Player *p)
ser_int(out, p->currently_inhabiting_index); ser_int(out, p->currently_inhabiting_index);
ser_V2(out, p->pos); ser_V2(out, p->pos);
ser_V2(out, p->vel); ser_V2(out, p->vel);
// input
ser_V2(out, p->movement); ser_V2(out, p->movement);
ser_bool(out, p->inhabit); ser_bool(out, p->inhabit);
ser_V2(out, p->build);
ser_bool(out, p->dobuild);
ser_int(out, p->grid_index);
} }
} }
@ -349,8 +361,14 @@ void des_player(char **in, struct Player *p, struct GameState *gs)
des_int(in, &p->currently_inhabiting_index); des_int(in, &p->currently_inhabiting_index);
des_V2(in, &p->pos); des_V2(in, &p->pos);
des_V2(in, &p->vel); des_V2(in, &p->vel);
// input
des_V2(in, &p->movement); des_V2(in, &p->movement);
des_bool(in, &p->inhabit); des_bool(in, &p->inhabit);
des_V2(in, &p->build);
des_bool(in, &p->dobuild);
des_int(in, &p->grid_index);
} }
} }
@ -430,7 +448,7 @@ static void closest_point_callback_func(cpShape *shape, cpContactPointSet *point
assert(points->count == 1); assert(points->count == 1);
float dist = V2length(cp_to_v2(cpvsub(points->points[0].pointA, points->points[0].pointB))); float dist = V2length(cp_to_v2(cpvsub(points->points[0].pointA, points->points[0].pointB)));
// float dist = -points->points[0].distance; // float dist = -points->points[0].distance;
if(dist > closest_to_point_in_radius_result_largest_dist) if (dist > closest_to_point_in_radius_result_largest_dist)
{ {
closest_to_point_in_radius_result_largest_dist = dist; closest_to_point_in_radius_result_largest_dist = dist;
closest_to_point_in_radius_result = shape; closest_to_point_in_radius_result = shape;
@ -442,7 +460,7 @@ struct Grid *closest_to_point_in_radius(struct GameState *gs, V2 point, float ra
closest_to_point_in_radius_result = NULL; closest_to_point_in_radius_result = NULL;
closest_to_point_in_radius_result_largest_dist = 0.0f; closest_to_point_in_radius_result_largest_dist = 0.0f;
cpBody * tmpbody = cpBodyNew(0.0f, 0.0f); cpBody *tmpbody = cpBodyNew(0.0f, 0.0f);
cpShape *circle = cpCircleShapeNew(tmpbody, radius, v2_to_cp(point)); cpShape *circle = cpCircleShapeNew(tmpbody, radius, v2_to_cp(point));
cpSpaceShapeQuery(gs->space, circle, closest_point_callback_func, NULL); cpSpaceShapeQuery(gs->space, circle, closest_point_callback_func, NULL);
@ -469,6 +487,53 @@ void process(struct GameState *gs, float dt)
if (!p->connected) if (!p->connected)
continue; continue;
if (p->dobuild)
{
p->dobuild = false; // handle the input. if didn't do this, after destruction of hovered box, would try to build on its grid with grid_index...
cpPointQueryInfo info = {0};
// @Robust make sure to query only against boxes...
cpShape *nearest = cpSpacePointQueryNearest(gs->space, v2_to_cp(p->build), 0.01f, cpShapeFilterNew(CP_NO_GROUP, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES), &info);
if (nearest != NULL)
{
struct Box *cur_box = (struct Box *)cpShapeGetUserData(nearest);
struct Grid *cur_grid = (struct Grid *)cpBodyGetUserData(cpShapeGetBody(nearest));
grid_remove_box(gs->space, cur_grid, cur_box);
}
else if(p->grid_index == -1)
{
// @Robust better memory mgmt
struct Grid *empty_grid = NULL;
for (int ii = 0; ii < MAX_GRIDS; ii++)
{
if (gs->grids[ii].body == NULL)
{
empty_grid = &gs->grids[ii];
break;
}
}
grid_new(empty_grid, gs, p->build);
box_new(&empty_grid->boxes[0], gs, empty_grid, (V2){0});
}
else
{
struct Grid *g = &gs->grids[p->grid_index];
struct Box *empty_box = NULL;
for (int ii = 0; ii < MAX_BOXES_PER_GRID; ii++)
{
if (g->boxes[ii].shape == NULL)
{
empty_box = &g->boxes[ii];
break;
}
}
// @Robust cleanly fail when not enough boxes
assert(empty_box != NULL);
box_new(empty_box, gs, g, grid_world_to_local(g, p->build));
}
}
if (gs->grids[p->currently_inhabiting_index].body == NULL) if (gs->grids[p->currently_inhabiting_index].body == NULL)
{ {
p->currently_inhabiting_index = -1; p->currently_inhabiting_index = -1;
@ -482,7 +547,7 @@ void process(struct GameState *gs, float dt)
// @Robust mask to only ship boxes of things the player can inhabit // @Robust mask to only ship boxes of things the player can inhabit
cpPointQueryInfo query_info = {0}; cpPointQueryInfo query_info = {0};
cpShape *result = cpSpacePointQueryNearest(gs->space, v2_to_cp(p->pos), 0.1, cpShapeFilterNew(CP_NO_GROUP, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES), &query_info); cpShape *result = cpSpacePointQueryNearest(gs->space, v2_to_cp(p->pos), 0.1f, cpShapeFilterNew(CP_NO_GROUP, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES), &query_info);
if (result != NULL) if (result != NULL)
{ {
// result is assumed to be a box shape // result is assumed to be a box shape
@ -515,7 +580,7 @@ void process(struct GameState *gs, float dt)
if (p->currently_inhabiting_index == -1) if (p->currently_inhabiting_index == -1)
{ {
p->vel = V2lerp(p->vel, p->movement, dt * 5.0f); p->vel = V2add(p->vel, V2scale(p->movement, dt*3.0f));
p->pos = V2add(p->pos, V2scale(p->vel, dt)); p->pos = V2add(p->pos, V2scale(p->vel, dt));
} }
else else
@ -524,7 +589,6 @@ void process(struct GameState *gs, float dt)
p->pos = V2lerp(p->pos, grid_com(g), dt * 20.0f); p->pos = V2lerp(p->pos, grid_com(g), dt * 20.0f);
cpBodyApplyForceAtWorldPoint(g->body, v2_to_cp(V2scale(p->movement, 5.0f)), v2_to_cp(grid_com(g))); cpBodyApplyForceAtWorldPoint(g->body, v2_to_cp(V2scale(p->movement, 5.0f)), v2_to_cp(grid_com(g)));
} }
// cpBodyApplyForceAtWorldPoint(p->box.body, v2_to_cp(V2scale(p->input, 5.0f)), v2_to_cp(box_pos(p->box)));
} }
cpSpaceStep(gs->space, dt); cpSpaceStep(gs->space, dt);

145
main.c

@ -16,7 +16,7 @@
static struct GameState gs = {0}; static struct GameState gs = {0};
static int myplayer = -1; static int myplayer = -1;
static bool mouse_down = false; static bool right_mouse_down = false;
static bool keydown[SAPP_KEYCODE_MENU] = {0}; static bool keydown[SAPP_KEYCODE_MENU] = {0};
typedef struct KeyPressed typedef struct KeyPressed
{ {
@ -25,6 +25,8 @@ typedef struct KeyPressed
} KeyPressed; } KeyPressed;
static KeyPressed keypressed[SAPP_KEYCODE_MENU] = {0}; static KeyPressed keypressed[SAPP_KEYCODE_MENU] = {0};
static V2 mouse_pos = {0}; static V2 mouse_pos = {0};
static bool mouse_pressed = false;
static uint64_t mouse_pressed_frame = 0;
static bool mouse_frozen = false; // @BeforeShip make this debug only thing static bool mouse_frozen = false; // @BeforeShip make this debug only thing
static float funval = 0.0f; // easy to play with value controlled by left mouse button when held down @BeforeShip remove on release builds static float funval = 0.0f; // easy to play with value controlled by left mouse button when held down @BeforeShip remove on release builds
static ENetHost *client; static ENetHost *client;
@ -134,11 +136,18 @@ static void frame(void)
float time = sapp_frame_count() * sapp_frame_duration(); float time = sapp_frame_count() * sapp_frame_duration();
float dt = sapp_frame_duration(); float dt = sapp_frame_duration();
for (int i = 0; i < SAPP_KEYCODE_MENU; i++) // pressed input management
{ {
if (keypressed[i].frame < sapp_frame_count()) for (int i = 0; i < SAPP_KEYCODE_MENU; i++)
{ {
keypressed[i].pressed = false; if (keypressed[i].frame < sapp_frame_count())
{
keypressed[i].pressed = false;
}
}
if (mouse_pressed_frame < sapp_frame_count())
{
mouse_pressed = false;
} }
} }
@ -189,19 +198,76 @@ static void frame(void)
// gameplay // gameplay
V2 build_target_pos = {0}; V2 build_target_pos = {0};
float build_target_rotation = 0.0f; float build_target_rotation = 0.0f;
V2 camera_pos = {0};
V2 world_mouse_pos = mouse_pos;
float zoom = 300.0f + funval;
struct BuildPreviewInfo
{
V2 grid_pos;
float grid_rotation;
V2 pos;
} build_preview = {0};
{ {
// @Robust accumulate total time and send input at rate like 20 hz, not every frame // calculate world position and camera
struct ClientToServer curmsg = {0}; {
V2 input = (V2){ if (myplayer != -1)
.x = (float)keydown[SAPP_KEYCODE_D] - (float)keydown[SAPP_KEYCODE_A], {
.y = (float)keydown[SAPP_KEYCODE_S] - (float)keydown[SAPP_KEYCODE_W], camera_pos = gs.players[myplayer].pos;
}; }
curmsg.movement = input; world_mouse_pos = V2sub(world_mouse_pos, (V2){.x = width / 2.0f, .y = height / 2.0f});
curmsg.inhabit = keypressed[SAPP_KEYCODE_G].pressed; world_mouse_pos.x /= zoom;
world_mouse_pos.y /= zoom;
// @BeforeShip figure out why tf the possess ship key is so unreliable world_mouse_pos = V2add(world_mouse_pos, (V2){.x = camera_pos.x, .y = camera_pos.y});
ENetPacket *packet = enet_packet_create((void *)&curmsg, sizeof(curmsg), ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT); }
enet_peer_send(peer, 0, packet);
// calculate build preview stuff
int grid_index = -1;
{
struct Grid *placing_grid = closest_to_point_in_radius(&gs, world_mouse_pos, 0.35f);
if (placing_grid == NULL)
{
build_preview = (struct BuildPreviewInfo){
.grid_pos = world_mouse_pos,
.grid_rotation = 0.0f,
.pos = world_mouse_pos,
};
}
else
{
for (int i = 0; i < MAX_GRIDS; i++)
{
if (&gs.grids[i] == placing_grid)
{
grid_index = i;
break;
}
}
V2 pos = grid_snapped_box_pos(placing_grid, world_mouse_pos);
build_preview = (struct BuildPreviewInfo){
.grid_pos = grid_pos(placing_grid),
.grid_rotation = grid_rotation(placing_grid),
.pos = pos};
}
}
// Create and send input packet
{
// @Robust accumulate total time and send input at rate like 20 hz, not every frame
struct ClientToServer curmsg = {0};
V2 input = (V2){
.x = (float)keydown[SAPP_KEYCODE_D] - (float)keydown[SAPP_KEYCODE_A],
.y = (float)keydown[SAPP_KEYCODE_S] - (float)keydown[SAPP_KEYCODE_W],
};
curmsg.movement = input;
curmsg.inhabit = keypressed[SAPP_KEYCODE_G].pressed;
curmsg.build = build_preview.pos;
curmsg.dobuild = mouse_pressed;
curmsg.grid_index = grid_index;
// @BeforeShip figure out why tf the possess ship key is so unreliable
ENetPacket *packet = enet_packet_create((void *)&curmsg, sizeof(curmsg), ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT);
enet_peer_send(peer, 0, packet);
}
// @BeforeShip client side prediction and rollback to previous server authoritative state, then replay inputs // @BeforeShip client side prediction and rollback to previous server authoritative state, then replay inputs
// no need to store copies of game state, just player input frame to frame. Then know how many frames ago the server game state arrived, it's that easy! // no need to store copies of game state, just player input frame to frame. Then know how many frames ago the server game state arrived, it's that easy!
@ -220,21 +286,13 @@ static void frame(void)
sgp_clear(); sgp_clear();
// sokol drawing library draw in world space // sokol drawing library draw in world space
V2 world_mouse_pos = mouse_pos;
{ {
float zoom = 300.0f + funval;
sgp_translate(width / 2, height / 2); sgp_translate(width / 2, height / 2);
world_mouse_pos = V2sub(world_mouse_pos, (V2){.x = width / 2.0f, .y = height / 2.0f});
sgp_scale_at(zoom, zoom, 0.0f, 0.0f); sgp_scale_at(zoom, zoom, 0.0f, 0.0f);
world_mouse_pos.x /= zoom;
world_mouse_pos.y /= zoom;
// camera go to player // camera go to player
if (myplayer != -1)
{ sgp_translate(-camera_pos.x, -camera_pos.y);
V2 pos = gs.players[myplayer].pos;
sgp_translate(-pos.x, -pos.y);
world_mouse_pos = V2add(world_mouse_pos, (V2){.x = pos.x, .y = pos.y});
}
} }
sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f); sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f);
@ -281,13 +339,11 @@ static void frame(void)
sgp_set_color(1.0f, 0.0f, 0.0f, 0.5f); sgp_set_color(1.0f, 0.0f, 0.0f, 0.5f);
sgp_draw_filled_rect(world_mouse_pos.x, world_mouse_pos.y, 0.1f, 0.1f); sgp_draw_filled_rect(world_mouse_pos.x, world_mouse_pos.y, 0.1f, 0.1f);
} }
struct Grid *placing_grid = closest_to_point_in_radius(&gs, world_mouse_pos, 0.35f);
if (placing_grid != NULL) // building preview
{ {
V2 pos = grid_snapped_box_pos(placing_grid, world_mouse_pos);
sgp_set_color(0.5f, 0.5f, 0.5f, (sin(time * 9.0f) + 1.0) / 3.0f + 0.2); sgp_set_color(0.5f, 0.5f, 0.5f, (sin(time * 9.0f) + 1.0) / 3.0f + 0.2);
drawbox(grid_pos(placing_grid), grid_rotation(placing_grid), pos, 0.0f, false); drawbox(build_preview.grid_pos, build_preview.grid_rotation, build_preview.pos, 0.0f, false);
// sgp_draw_filled_rect(pos.x, pos.y, 0.1f, 0.1f);
} }
// grids // grids
@ -317,11 +373,6 @@ static void frame(void)
sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f); sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f);
dbg_drawall(); dbg_drawall();
// sgp_draw_line(5.0f, 5.0f, 5.0f, 10.0f);
// sgp_draw_line()
// sgp_rotate_at(time, 0.0f, 0.0f);
// Begin a render pass.
sg_pass_action pass_action = {0}; sg_pass_action pass_action = {0};
sg_begin_default_pass(&pass_action, width, height); sg_begin_default_pass(&pass_action, width, height);
sgp_flush(); sgp_flush();
@ -362,18 +413,32 @@ void event(const sapp_event *e)
break; break;
case SAPP_EVENTTYPE_MOUSE_DOWN: case SAPP_EVENTTYPE_MOUSE_DOWN:
if (e->mouse_button == SAPP_MOUSEBUTTON_LEFT) if (e->mouse_button == SAPP_MOUSEBUTTON_LEFT)
mouse_down = true; {
mouse_pressed = true;
mouse_pressed_frame = e->frame_count;
}
if (e->mouse_button == SAPP_MOUSEBUTTON_RIGHT)
{
right_mouse_down = true;
}
break; break;
case SAPP_EVENTTYPE_MOUSE_UP: case SAPP_EVENTTYPE_MOUSE_UP:
if (e->mouse_button == SAPP_MOUSEBUTTON_LEFT) if (e->mouse_button == SAPP_MOUSEBUTTON_LEFT)
mouse_down = false; {
mouse_pressed = false;
mouse_pressed_frame = 0;
}
if (e->mouse_button == SAPP_MOUSEBUTTON_RIGHT)
{
right_mouse_down = false;
}
break; break;
case SAPP_EVENTTYPE_MOUSE_MOVE: case SAPP_EVENTTYPE_MOUSE_MOVE:
if (!mouse_frozen) if (!mouse_frozen)
{ {
mouse_pos = (V2){.x = e->mouse_x, .y = e->mouse_y}; mouse_pos = (V2){.x = e->mouse_x, .y = e->mouse_y};
} }
if (mouse_down) if (right_mouse_down)
{ {
funval += e->mouse_dx; funval += e->mouse_dx;
Log("Funval %f\n", funval); Log("Funval %f\n", funval);

@ -17,37 +17,36 @@ void server(void *data)
initialize(&gs); initialize(&gs);
// box haven // box haven
if(true) if (true)
{ {
grid_new(&gs.grids[0], &gs, (V2){.x = 0.75f, .y = 0.0}); grid_new(&gs.grids[0], &gs, (V2){.x = 0.75f, .y = 0.0});
box_new(&gs.grids[0].boxes[0],&gs, &gs.grids[0], (V2){0}); box_new(&gs.grids[0].boxes[0], &gs, &gs.grids[0], (V2){0});
box_new(&gs.grids[0].boxes[1],&gs, &gs.grids[0], (V2){0, 0.5f}); box_new(&gs.grids[0].boxes[1], &gs, &gs.grids[0], (V2){0, 0.5f});
box_new(&gs.grids[0].boxes[2],&gs, &gs.grids[0], (V2){0, 1.0f}); box_new(&gs.grids[0].boxes[2], &gs, &gs.grids[0], (V2){0, 1.0f});
box_new(&gs.grids[0].boxes[3],&gs, &gs.grids[0], (V2){0.5f, 1.0f}); box_new(&gs.grids[0].boxes[3], &gs, &gs.grids[0], (V2){0.5f, 1.0f});
grid_new(&gs.grids[1], &gs, (V2){.x = -0.75f, .y = 0.0}); grid_new(&gs.grids[1], &gs, (V2){.x = -0.75f, .y = 0.0});
box_new(&gs.grids[1].boxes[0],&gs, &gs.grids[1], (V2){0}); box_new(&gs.grids[1].boxes[0], &gs, &gs.grids[1], (V2){0});
grid_new(&gs.grids[2], &gs, (V2){.x = -0.75f, .y = 0.5}); grid_new(&gs.grids[2], &gs, (V2){.x = -0.75f, .y = 0.5});
box_new(&gs.grids[2].boxes[0],&gs, &gs.grids[2], (V2){0}); box_new(&gs.grids[2].boxes[0], &gs, &gs.grids[2], (V2){0});
} }
// two boxes // two boxes
if (false) if (false)
{ {
grid_new(&gs.grids[0], &gs, (V2){.x = 0.75f, .y = 0.0}); grid_new(&gs.grids[0], &gs, (V2){.x = 0.75f, .y = 0.0});
box_new(&gs.grids[0].boxes[0],&gs, &gs.grids[0], (V2){0}); box_new(&gs.grids[0].boxes[0], &gs, &gs.grids[0], (V2){0});
grid_new(&gs.grids[1], &gs, (V2){.x = -1.75f, .y = 0.0}); grid_new(&gs.grids[1], &gs, (V2){.x = -1.75f, .y = 0.0});
box_new(&gs.grids[1].boxes[1],&gs, &gs.grids[1], (V2){1}); box_new(&gs.grids[1].boxes[1], &gs, &gs.grids[1], (V2){1});
} }
// one box policy // one box policy
if (false) if (false)
{ {
grid_new(&gs.grids[0], &gs, (V2){.x = 0.75f, .y = 0.0}); grid_new(&gs.grids[0], &gs, (V2){.x = 0.75f, .y = 0.0});
box_new(&gs.grids[0].boxes[0],&gs, &gs.grids[0], (V2){0}); box_new(&gs.grids[0].boxes[0], &gs, &gs.grids[0], (V2){0});
} }
if (enet_initialize() != 0) if (enet_initialize() != 0)
@ -82,7 +81,7 @@ void server(void *data)
// @Speed handle enet messages and simulate gamestate in parallel, then sync... must clone gamestate for this // @Speed handle enet messages and simulate gamestate in parallel, then sync... must clone gamestate for this
while (true) while (true)
{ {
int ret = enet_host_service(server, &event, 16); int ret = enet_host_service(server, &event, 0);
if (ret == 0) if (ret == 0)
break; break;
if (ret < 0) if (ret < 0)
@ -141,6 +140,9 @@ void server(void *data)
int64_t player_slot = (int64_t)event.peer->data; int64_t player_slot = (int64_t)event.peer->data;
gs.players[player_slot].movement = received.movement; gs.players[player_slot].movement = received.movement;
gs.players[player_slot].inhabit = received.inhabit; gs.players[player_slot].inhabit = received.inhabit;
gs.players[player_slot].build = received.build;
gs.players[player_slot].dobuild = received.dobuild;
gs.players[player_slot].grid_index = received.grid_index;
} }
/* Clean up the packet now that we're done using it. */ /* Clean up the packet now that we're done using it. */
@ -161,30 +163,35 @@ void server(void *data)
total_time += (float)stm_sec(stm_diff(stm_now(), last_processed_time)); total_time += (float)stm_sec(stm_diff(stm_now(), last_processed_time));
last_processed_time = stm_now(); last_processed_time = stm_now();
// @Robost @BeforeShip 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...
bool processed = false;
while (total_time > TIMESTEP) while (total_time > TIMESTEP)
{ {
processed = true;
process(&gs, TIMESTEP); process(&gs, TIMESTEP);
total_time -= TIMESTEP; total_time -= TIMESTEP;
} }
#define MAX_BYTES_SIZE 2048 * 2 if (processed)
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 #define MAX_BYTES_SIZE 2048 * 2
if (server->peers[i].state != ENET_PEER_STATE_CONNECTED) static char bytes_buffer[MAX_BYTES_SIZE] = {0};
for (int i = 0; i < server->peerCount; i++)
{ {
continue; // @Speed don't recreate the packet for every peer, gets expensive copying gamestate over and over again
} if (server->peers[i].state != ENET_PEER_STATE_CONNECTED)
struct ServerToClient to_send; {
to_send.cur_gs = &gs; continue;
to_send.your_player = (int)(int64_t)server->peers[i].data; }
struct ServerToClient to_send;
to_send.cur_gs = &gs;
to_send.your_player = (int)(int64_t)server->peers[i].data;
int len = 0; int len = 0;
into_bytes(&to_send, bytes_buffer, &len, MAX_BYTES_SIZE); 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); ENetPacket *gamestate_packet = enet_packet_create((void *)bytes_buffer, len, ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT);
enet_peer_send(&server->peers[i], 0, gamestate_packet); enet_peer_send(&server->peers[i], 0, gamestate_packet);
}
} }
} }

@ -60,6 +60,10 @@ struct GameState
// input // input
V2 movement; V2 movement;
bool inhabit; bool inhabit;
V2 build; // @Robust this is messy, clean up?
bool dobuild;
int grid_index;
} players[MAX_PLAYERS]; } players[MAX_PLAYERS];
// if body or shape is null, then that grid/box has been freed // if body or shape is null, then that grid/box has been freed
@ -87,6 +91,9 @@ struct ClientToServer
{ {
V2 movement; V2 movement;
bool inhabit; bool inhabit;
V2 build;
bool dobuild;
int grid_index;
}; };
// server // server

Loading…
Cancel
Save