Separate player and partial entity refactor

main
Cameron Murphy Reikes 2 years ago
parent e05462aa1b
commit 5af0639504

@ -51,6 +51,7 @@
"xmemory": "c", "xmemory": "c",
"xtr1common": "c", "xtr1common": "c",
"xtree": "c", "xtree": "c",
"stdint.h": "c" "stdint.h": "c",
"ipsettings.h": "c"
} }
} }

@ -13,6 +13,7 @@ pushd thirdparty\Chipmunk2D\src
for %%x in (*.c) do set MUNKSRC=!MUNKSRC! thirdparty\Chipmunk2D\src\%%x for %%x in (*.c) do set MUNKSRC=!MUNKSRC! thirdparty\Chipmunk2D\src\%%x
popd popd
@REM /DENET_DEBUG=1^
cl /MP /Zi /Fd"flight.pdb" /Fe"flight"^ cl /MP /Zi /Fd"flight.pdb" /Fe"flight"^
/I"thirdparty" /I"thirdparty\enet\include" /I"thirdparty\Chipmunk2D\include\chipmunk" /I"thirdparty\Chipmunk2D\include"^ /I"thirdparty" /I"thirdparty\enet\include" /I"thirdparty\Chipmunk2D\include\chipmunk" /I"thirdparty\Chipmunk2D\include"^
main.c gamestate.c server.c debugdraw.c^ main.c gamestate.c server.c debugdraw.c^

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 734 B

304
main.c

@ -42,6 +42,7 @@ static float zoom = 300.0f;
static sg_image image_itemframe; static sg_image image_itemframe;
static sg_image image_itemframe_selected; static sg_image image_itemframe_selected;
static sg_image image_thrusterburn; static sg_image image_thrusterburn;
static sg_image image_player;
static int cur_editing_boxtype = -1; static int cur_editing_boxtype = -1;
static int cur_editing_rotation = 0; static int cur_editing_rotation = 0;
@ -110,7 +111,8 @@ static void init(void)
{ {
// @BeforeShip make all fprintf into logging to file, warning dialog grids on failure instead of exit(-1), replace the macros in sokol with this as well, like assert // @BeforeShip make all fprintf into logging to file, warning dialog grids on failure instead of exit(-1), replace the macros in sokol with this as well, like assert
initialize(&gs); Entity *entity_data = malloc(sizeof *entity_data * MAX_ENTITIES);
initialize(&gs, entity_data, sizeof *entity_data * MAX_ENTITIES);
sg_desc sgdesc = {.context = sapp_sgcontext()}; sg_desc sgdesc = {.context = sapp_sgcontext()};
sg_setup(&sgdesc); sg_setup(&sgdesc);
@ -137,6 +139,7 @@ static void init(void)
image_thrusterburn = load_image("loaded/thrusterburn.png"); image_thrusterburn = load_image("loaded/thrusterburn.png");
image_itemframe = load_image("loaded/itemframe.png"); image_itemframe = load_image("loaded/itemframe.png");
image_itemframe_selected = load_image("loaded/itemframe_selected.png"); image_itemframe_selected = load_image("loaded/itemframe_selected.png");
image_player = load_image("loaded/player.png");
} }
// socket initialization // socket initialization
@ -187,25 +190,8 @@ static void init(void)
} }
} }
// static void drawbox(V2 boxpos, float rot, float damage, enum BoxType type, enum Rotation rotation) #define DeferLoop(start, end) for (int _i_ = ((start), 0); _i_ == 0; _i_ += 1, (end))
// { #define transform_scope DeferLoop(sgp_push_transform(), sgp_pop_transform())
// sgp_push_transform();
// sgp_rotate_at(rot, boxpos.x, boxpos.y);
// sgp_set_image(0, boxinfo(type).image);
// sgp_rotate_at(rotangle(rotation), boxpos.x, boxpos.y);
// sgp_reset_image(0);
// if (damage > 0.0f)
// {
// sgp_set_color(0.5f, 0.1f, 0.1f, damage);
// }
// sgp_pop_transform();
// }
static void draw_color_rect_centered(V2 center, float size) static void draw_color_rect_centered(V2 center, float size)
{ {
@ -214,10 +200,15 @@ static void draw_color_rect_centered(V2 center, float size)
sgp_draw_filled_rect(center.x - halfbox, center.y - halfbox, size, size); sgp_draw_filled_rect(center.x - halfbox, center.y - halfbox, size, size);
} }
static void draw_texture_rectangle_centered(V2 center, V2 width_height)
{
V2 halfsize = V2scale(width_height, 0.5f);
sgp_draw_textured_rect(center.x - halfsize.x, center.y - halfsize.y, width_height.x, width_height.y);
}
static void draw_texture_centered(V2 center, float size) static void draw_texture_centered(V2 center, float size)
{ {
float halfbox = size / 2.0f; draw_texture_rectangle_centered(center, (V2){size, size});
sgp_draw_textured_rect(center.x - halfbox, center.y - halfbox, BOX_SIZE, BOX_SIZE);
} }
static void draw_circle(V2 point, float radius) static void draw_circle(V2 point, float radius)
@ -236,22 +227,45 @@ static void draw_circle(V2 point, float radius)
sgp_draw_lines(lines, POINTS); sgp_draw_lines(lines, POINTS);
} }
static void ui(bool draw, float width, float height) static Entity *myentity()
{
if (myplayer == -1)
return NULL;
Entity *to_return = get_entity(&gs, gs.players[myplayer].entity);
if (to_return != NULL)
assert(to_return->is_player);
return to_return;
}
static void ui(bool draw, float dt, float width, float height)
{ {
static float cur_opacity = 1.0f;
cur_opacity = lerp(cur_opacity, myentity() != NULL ? 1.0f : 0.0f, dt * 5.0f);
if (cur_opacity <= 0.01f)
{
return;
}
// draw spice bar // draw spice bar
if (draw && myplayer != -1) if (draw)
{ {
sgp_set_color(0.5f, 0.5f, 0.5f, 1.0f); static float spice_taken_away = 0.5f;
if (myentity() != NULL)
{
spice_taken_away = myentity()->spice_taken_away;
}
sgp_set_color(0.5f, 0.5f, 0.5f, cur_opacity);
float margin = width * 0.1; float margin = width * 0.1;
float bar_width = width - margin * 2.0f; float bar_width = width - margin * 2.0f;
sgp_draw_filled_rect(margin, 80.0f, bar_width, 30.0f); sgp_draw_filled_rect(margin, 80.0f, bar_width, 30.0f);
sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f); sgp_set_color(1.0f, 1.0f, 1.0f, cur_opacity);
sgp_draw_filled_rect(margin, 80.0f, bar_width * (1.0f - gs.players[myplayer].spice_taken_away), 30.0f); sgp_draw_filled_rect(margin, 80.0f, bar_width * (1.0f - spice_taken_away), 30.0f);
} }
// draw item toolbar // draw item toolbar
{ {
int itemframe_width = sg_query_image_info(image_itemframe).width * 2.0f; int itemframe_width = sg_query_image_info(image_itemframe).width * 2.0f;
int itemframe_height = sg_query_image_info(image_itemframe).height * 2.0f; int itemframe_height = sg_query_image_info(image_itemframe).height * 2.0f;
int total_width = itemframe_width * boxes_len; int total_width = itemframe_width * boxes_len;
@ -279,7 +293,7 @@ static void ui(bool draw, float width, float height)
} }
if (draw) if (draw)
{ {
sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f); sgp_set_color(1.0f, 1.0f, 1.0f, cur_opacity);
if (cur_editing_boxtype == i) if (cur_editing_boxtype == i)
{ {
sgp_set_image(0, image_itemframe_selected); sgp_set_image(0, image_itemframe_selected);
@ -366,10 +380,10 @@ static void frame(void)
} }
// gameplay // gameplay
ui(false, width, height); // handle events ui(false, dt, width, height); // handle events
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}; static V2 camera_pos = {0}; // keeps camera at same position after player death
V2 world_mouse_pos = mouse_pos; V2 world_mouse_pos = mouse_pos;
struct BuildPreviewInfo struct BuildPreviewInfo
{ {
@ -384,9 +398,10 @@ static void frame(void)
// calculate world position and camera // calculate world position and camera
{ {
if (myplayer != -1) if (myentity() != NULL)
{ {
camera_pos = gs.players[myplayer].pos;
camera_pos = entity_pos(myentity());
} }
world_mouse_pos = V2sub(world_mouse_pos, (V2){.x = width / 2.0f, .y = height / 2.0f}); world_mouse_pos = V2sub(world_mouse_pos, (V2){.x = width / 2.0f, .y = height / 2.0f});
world_mouse_pos.x /= zoom; world_mouse_pos.x /= zoom;
@ -395,10 +410,10 @@ static void frame(void)
} }
// calculate build preview stuff // calculate build preview stuff
int grid_index = -1; EntityID grid_to_build_on = (EntityID){0};
if (myplayer != -1) if (myentity() != NULL)
{ {
V2 hand_pos = V2sub(world_mouse_pos, gs.players[myplayer].pos); V2 hand_pos = V2sub(world_mouse_pos, entity_pos(myentity()));
float hand_len = V2length(hand_pos); float hand_len = V2length(hand_pos);
if (hand_len > MAX_HAND_REACH) if (hand_len > MAX_HAND_REACH)
{ {
@ -410,9 +425,9 @@ static void frame(void)
hand_at_arms_length = false; hand_at_arms_length = false;
} }
hand_pos = V2scale(V2normalize(hand_pos), hand_len); hand_pos = V2scale(V2normalize(hand_pos), hand_len);
hand_pos = V2add(hand_pos, gs.players[myplayer].pos); hand_pos = V2add(hand_pos, entity_pos(myentity()));
struct Grid *placing_grid = closest_to_point_in_radius(&gs, hand_pos, BUILD_BOX_SNAP_DIST_TO_SHIP); Entity *placing_grid = closest_to_point_in_radius(&gs, hand_pos, BUILD_BOX_SNAP_DIST_TO_SHIP);
if (placing_grid == NULL) if (placing_grid == NULL)
{ {
build_preview = (struct BuildPreviewInfo){ build_preview = (struct BuildPreviewInfo){
@ -423,18 +438,11 @@ static void frame(void)
} }
else else
{ {
for (int i = 0; i < MAX_GRIDS; i++) grid_to_build_on = get_id(&gs, placing_grid);
{
if (&gs.grids[i] == placing_grid)
{
grid_index = i;
break;
}
}
V2 pos = grid_snapped_box_pos(placing_grid, hand_pos); V2 pos = grid_snapped_box_pos(placing_grid, hand_pos);
build_preview = (struct BuildPreviewInfo){ build_preview = (struct BuildPreviewInfo){
.grid_pos = grid_pos(placing_grid), .grid_pos = entity_pos(placing_grid),
.grid_rotation = grid_rotation(placing_grid), .grid_rotation = entity_rotation(placing_grid),
.pos = pos}; .pos = pos};
} }
} }
@ -455,12 +463,11 @@ static void frame(void)
cur_input_frame.dobuild = mouse_pressed; cur_input_frame.dobuild = mouse_pressed;
cur_input_frame.build_type = cur_editing_boxtype; cur_input_frame.build_type = cur_editing_boxtype;
cur_input_frame.build_rotation = cur_editing_rotation; cur_input_frame.build_rotation = cur_editing_rotation;
cur_input_frame.grid_index = grid_index; cur_input_frame.grid_to_build_on = grid_to_build_on;
if (grid_index != -1) Entity *grid = get_entity(&gs, grid_to_build_on);
if (grid != NULL)
{ {
cur_input_frame.build = grid_world_to_local(&gs.grids[cur_input_frame.grid_index], build_preview.pos); cur_input_frame.build = grid_world_to_local(grid, build_preview.pos);
V2 untransformed = grid_local_to_world(&gs.grids[cur_input_frame.grid_index], cur_input_frame.build);
untransformed.x += 5.0f;
} }
else else
{ {
@ -474,14 +481,15 @@ static void frame(void)
!V2cmp(cur_input_frame.movement, latest.movement, 0.01f) || !V2cmp(cur_input_frame.movement, latest.movement, 0.01f) ||
cur_input_frame.inhabit != latest.inhabit || cur_input_frame.inhabit != latest.inhabit ||
cur_input_frame.dobuild != latest.dobuild || cur_input_frame.dobuild != latest.dobuild ||
cur_input_frame.grid_index != latest.grid_index || cur_input_frame.grid_to_build_on.generation != latest.grid_to_build_on.generation ||
cur_input_frame.grid_to_build_on.index != latest.grid_to_build_on.index ||
!V2cmp(cur_input_frame.build, latest.build, 0.01f)) !V2cmp(cur_input_frame.build, latest.build, 0.01f))
{ {
for (int i = 0; i < INPUT_BUFFER - 1; i++) for (int i = 0; i < INPUT_BUFFER - 1; i++)
{ {
client_to_server.inputs[i + 1] = client_to_server.inputs[i]; client_to_server.inputs[i + 1] = client_to_server.inputs[i];
} }
cur_input_frame.tick = gs.tick; cur_input_frame.tick = tick(&gs);
client_to_server.inputs[0] = cur_input_frame; client_to_server.inputs[0] = cur_input_frame;
} }
@ -512,8 +520,7 @@ static void frame(void)
// sokol drawing library draw in world space // sokol drawing library draw in world space
// world space coordinates are +Y up, -Y down. Like normal cartesian coords // world space coordinates are +Y up, -Y down. Like normal cartesian coords
{ transform_scope {
sgp_push_transform();
sgp_translate(width / 2, height / 2); sgp_translate(width / 2, height / 2);
sgp_scale_at(zoom, -zoom, 0.0f, 0.0f); sgp_scale_at(zoom, -zoom, 0.0f, 0.0f);
@ -521,17 +528,17 @@ static void frame(void)
sgp_translate(-camera_pos.x, -camera_pos.y); sgp_translate(-camera_pos.x, -camera_pos.y);
// hand reached limit circle // hand reached limit circle
if (myplayer != -1) if (myentity() != NULL)
{ {
static float hand_reach_alpha = 1.0f; static float hand_reach_alpha = 1.0f;
hand_reach_alpha = lerp(hand_reach_alpha, hand_at_arms_length ? 1.0f : 0.0f, dt * 5.0); hand_reach_alpha = lerp(hand_reach_alpha, hand_at_arms_length ? 1.0f : 0.0f, dt * 5.0);
sgp_set_color(1.0f, 1.0f, 1.0f, hand_reach_alpha); sgp_set_color(1.0f, 1.0f, 1.0f, hand_reach_alpha);
draw_circle(gs.players[myplayer].pos, MAX_HAND_REACH); draw_circle(entity_pos(myentity()), MAX_HAND_REACH);
} }
// stars // stars
sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f); sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f);
const int num = 50; const int num = 30;
for (int x = -num; x < num; x++) for (int x = -num; x < num; x++)
{ {
for (int y = -num; y < num; y++) for (int y = -num; y < num; y++)
@ -554,30 +561,30 @@ static void frame(void)
{ {
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);
sgp_push_transform(); transform_scope
{
sgp_set_image(0, boxinfo(cur_editing_boxtype).image);
sgp_rotate_at(build_preview.grid_rotation + rotangle(cur_editing_rotation), build_preview.pos.x, build_preview.pos.y);
draw_texture_centered(build_preview.pos, BOX_SIZE);
// drawbox(build_preview.pos, build_preview.grid_rotation, 0.0f, cur_editing_boxtype, cur_editing_rotation);
sgp_reset_image(0);
sgp_pop_transform(); sgp_set_image(0, boxinfo(cur_editing_boxtype).image);
sgp_rotate_at(build_preview.grid_rotation + rotangle(cur_editing_rotation), build_preview.pos.x, build_preview.pos.y);
draw_texture_centered(build_preview.pos, BOX_SIZE);
// drawbox(build_preview.pos, build_preview.grid_rotation, 0.0f, cur_editing_boxtype, cur_editing_rotation);
sgp_reset_image(0);
}
} }
// grids for (int i = 0; i < gs.cur_next_entity; i++)
{ {
for (int i = 0; i < MAX_GRIDS; i++) Entity *e = &gs.entities[i];
if (!e->exists)
continue;
if (e->is_grid) // grid drawing
{ {
SKIPNULL(gs.grids[i].body); Entity *g = e;
struct Grid *g = &gs.grids[i]; BOXES_ITER(&gs, b, g)
for (int ii = 0; ii < MAX_BOXES_PER_GRID; ii++)
{ {
SKIPNULL(g->boxes[ii].shape);
struct Box *b = &g->boxes[ii];
sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f); sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f);
// debug draw force vectors for thrusters // debug draw force vectors for thrusters
if (false) #if 0
{ {
if (b->type == BoxThruster) if (b->type == BoxThruster)
{ {
@ -585,7 +592,8 @@ static void frame(void)
dbg_line(box_pos(b), V2add(box_pos(b), V2scale(thruster_force(b), -1.0f))); dbg_line(box_pos(b), V2add(box_pos(b), V2scale(thruster_force(b), -1.0f)));
} }
} }
if (b->type == BoxBattery) #endif
if (b->box_type == BoxBattery)
{ {
float cur_alpha = sgp_get_color().a; float cur_alpha = sgp_get_color().a;
Color from = WHITE; Color from = WHITE;
@ -593,95 +601,105 @@ static void frame(void)
Color result = Collerp(from, to, b->energy_used); Color result = Collerp(from, to, b->energy_used);
sgp_set_color(result.r, result.g, result.b, cur_alpha); sgp_set_color(result.r, result.g, result.b, cur_alpha);
} }
sgp_push_transform(); transform_scope {
sgp_rotate_at(grid_rotation(g) + rotangle(b->compass_rotation), box_pos(b).x, box_pos(b).y); sgp_rotate_at(entity_rotation(g) + rotangle(b->compass_rotation), box_pos(b).x, box_pos(b).y);
if (b->type == BoxThruster) if (b->box_type == BoxThruster)
{ {
sgp_push_transform(); transform_scope
sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f); {
sgp_set_image(0, image_thrusterburn); sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f);
// float scaling = 1.0 + (hash11(time*3.0)/2.0)*lerp(0.0, 0.07, b->thrust); sgp_set_image(0, image_thrusterburn);
// printf("%f\n", b->thrust); // float scaling = 1.0 + (hash11(time*3.0)/2.0)*lerp(0.0, 0.07, b->thrust);
float scaling = 0.95 + lerp(0.0, 0.3,b->thrust); // printf("%f\n", b->thrust);
// float scaling = 1.1; float scaling = 0.95 + lerp(0.0, 0.3, b->thrust);
// sgp_translate(-(scaling*BOX_SIZE - BOX_SIZE), 0.0); // float scaling = 1.1;
// sgp_scale(scaling, 1.0); // sgp_translate(-(scaling*BOX_SIZE - BOX_SIZE), 0.0);
sgp_scale_at(scaling, 1.0, box_pos(b).x, box_pos(b).y); // sgp_scale(scaling, 1.0);
sgp_scale_at(scaling, 1.0, box_pos(b).x, box_pos(b).y);
draw_texture_centered(box_pos(b), BOX_SIZE);
sgp_reset_image(0);
}
}
sgp_set_image(0, boxinfo(b->box_type).image);
draw_texture_centered(box_pos(b), BOX_SIZE); draw_texture_centered(box_pos(b), BOX_SIZE);
sgp_reset_image(0); sgp_reset_image(0);
sgp_pop_transform();
}
sgp_set_color(0.5f, 0.1f, 0.1f, b->damage);
sgp_set_image(0, boxinfo(b->type).image); draw_color_rect_centered(box_pos(b), BOX_SIZE);
draw_texture_centered(box_pos(b), BOX_SIZE); }
sgp_reset_image(0);
sgp_set_color(0.5f, 0.1f, 0.1f, b->damage);
draw_color_rect_centered(box_pos(b), BOX_SIZE);
sgp_pop_transform();
} }
sgp_set_color(1.0f, 0.0f, 0.0f, 1.0f); sgp_set_color(1.0f, 0.0f, 0.0f, 1.0f);
V2 vel = grid_vel(&gs.grids[i]); V2 vel = grid_vel(g);
V2 to = V2add(grid_com(g), vel); V2 to = V2add(grid_com(g), vel);
sgp_draw_line(grid_com(g).x, grid_com(g).y, to.x, to.y); sgp_draw_line(grid_com(g).x, grid_com(g).y, to.x, to.y);
} }
if (e->is_player)
{
transform_scope
{
sgp_rotate_at(entity_rotation(e), entity_pos(e).x, entity_pos(e).y);
sgp_set_color(1.0f, 0.5f, 0.5f, 1.0f);
sgp_set_image(0, image_player);
draw_texture_rectangle_centered(entity_pos(e), PLAYER_SIZE);
sgp_reset_image(0);
}
}
} }
}
// player // player
for (int i = 0; i < MAX_PLAYERS; i++) for (int i = 0; i < MAX_PLAYERS; i++)
{
struct Player *player = &gs.players[i];
if (!player->connected)
continue;
Entity *p = get_entity(&gs, player->entity);
if (p == NULL)
continue;
static float opacities[MAX_PLAYERS] = {1.0f};
static V2 positions[MAX_PLAYERS] = {0};
opacities[i] = lerp(opacities[i], p != NULL ? 1.0f : 0.1f, dt * 7.0f);
Color col_to_draw = Collerp(WHITE, GOLD, p->goldness);
col_to_draw.a = opacities[i];
if (p != NULL)
{ {
struct Player *p = &gs.players[i]; positions[i] = entity_pos(p);
if (!p->connected) }
continue;
static float opacities[MAX_PLAYERS] = {1.0f};
opacities[i] = lerp(opacities[i], p->currently_inhabiting_index == -1 ? 1.0f : 0.1f, dt * 7.0f);
Color col_to_draw = Collerp(WHITE, GOLD, p->goldness);
col_to_draw.a = opacities[i];
set_color(col_to_draw); set_color(col_to_draw);
sgp_push_transform(); transform_scope
{
float psize = 0.1f; float psize = 0.1f;
sgp_draw_filled_rect(p->pos.x - psize / 2.0f, p->pos.y - psize / 2.0f, psize, psize); sgp_draw_filled_rect(positions[i].x - psize / 2.0f, positions[i].y - psize / 2.0f, psize, psize);
sgp_pop_transform();
// sgp_rotate_at(grid_rotation(p->grid), grid_pos(p->grid).x, grid_pos(p->grid).y);
// V2 bpos = grid_pos(p->grid);
// sgp_draw_filled_rect(grid_pos(p->grid).x - halfbox, grid_pos(p->grid).y - halfbox, BOX_SIZE, BOX_SIZE);
// sgp_pop_transform();
// sgp_set_color(1.0f, 0.0f, 0.0f, 1.0f);
// V2 vel = grid_vel(p->grid);
// V2 to = V2add(grid_pos(p->grid), vel);
// sgp_draw_line(grid_pos(p->grid).x, grid_pos(p->grid).y, to.x, to.y);
} }
// gold target
set_color(GOLD);
sgp_draw_filled_rect(gs.goldpos.x, gs.goldpos.y, 0.1f, 0.1f);
sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f);
dbg_drawall();
sgp_pop_transform();
} }
// UI drawn in screen space // gold target
ui(true, width, height); set_color(GOLD);
sgp_draw_filled_rect(gs.goldpos.x, gs.goldpos.y, 0.1f, 0.1f);
sg_pass_action pass_action = {0}; sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f);
sg_begin_default_pass(&pass_action, width, height); dbg_drawall();
sgp_flush();
sgp_end();
sg_end_pass();
sg_commit();
} }
// UI drawn in screen space
ui(true, dt, width, height);
sg_pass_action pass_action = {0};
sg_begin_default_pass(&pass_action, width, height);
sgp_flush();
sgp_end();
sg_end_pass();
sg_commit();
} }
void cleanup(void) void cleanup(void)
{ {
free(gs.entities);
destroy(&gs); destroy(&gs);
sgp_shutdown(); sgp_shutdown();
sg_shutdown(); sg_shutdown();

@ -3,6 +3,7 @@
#include <enet/enet.h> #include <enet/enet.h>
#include <stdio.h> #include <stdio.h>
#include <inttypes.h> // int64 printing #include <inttypes.h> // int64 printing
#include <stdlib.h>
// started in a thread from host // started in a thread from host
void server(void *data) void server(void *data)
@ -12,48 +13,20 @@ void server(void *data)
stm_setup(); stm_setup();
struct GameState gs = {0}; struct GameState gs = {0};
initialize(&gs); size_t entities_size = (sizeof(Entity) * MAX_ENTITIES);
Entity *entity_data = malloc(entities_size);
initialize(&gs, entity_data, entities_size);
Log("Allocated %zu bytes for entities\n", entities_size);
// box haven // one box policy
if (true) if (true)
{ {
grid_new(&gs.grids[0], &gs, (V2){.x = BOX_SIZE*3.0, .y = 0.0}); Entity * grid = new_entity(&gs);
box_new(&gs.grids[0].boxes[0], &gs, &gs.grids[0], (V2){0}); grid_create(&gs, grid);
box_new(&gs.grids[0].boxes[1], &gs, &gs.grids[0], (V2){0, BOX_SIZE}); entity_set_pos(grid, (V2){-BOX_SIZE*2, 0.0f});
box_new(&gs.grids[0].boxes[2], &gs, &gs.grids[0], (V2){0, BOX_SIZE*2.0}); Entity * box = new_entity(&gs);
gs.grids[0].boxes[2].type = BoxBattery; box_create(&gs, box, grid, (V2){0});
box_new(&gs.grids[0].boxes[3], &gs, &gs.grids[0], (V2){BOX_SIZE, BOX_SIZE*2.0});
gs.grids[0].boxes[3].type = BoxThruster;
gs.grids[0].boxes[3].compass_rotation = Right;
box_new(&gs.grids[0].boxes[4], &gs, &gs.grids[0], (V2){0, BOX_SIZE*3.0});
gs.grids[0].boxes[4].type = BoxThruster;
gs.grids[0].boxes[4].compass_rotation = Up;
grid_new(&gs.grids[1], &gs, (V2){.x = -BOX_SIZE*1.5, .y = 0.0});
box_new(&gs.grids[1].boxes[0], &gs, &gs.grids[1], (V2){0});
grid_new(&gs.grids[2], &gs, (V2){.x = -BOX_SIZE*1.5, .y = BOX_SIZE});
box_new(&gs.grids[2].boxes[0], &gs, &gs.grids[2], (V2){0});
}
// two boxes
if (false)
{
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});
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});
}
// one box policy
if (false)
{
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});
} }
if (enet_initialize() != 0) if (enet_initialize() != 0)
@ -126,11 +99,7 @@ void server(void *data)
else else
{ {
event.peer->data = (void *)player_slot; event.peer->data = (void *)player_slot;
reset_player(&gs.players[player_slot]); gs.players[player_slot] = (struct Player){0};
// gs.players[player_slot].box = box_new(&gs, (V2){
// .x = 0.0f,
// .y = 1.0f * (float)player_slot,
// });
gs.players[player_slot].connected = true; gs.players[player_slot].connected = true;
} }
@ -158,7 +127,7 @@ void server(void *data)
{ {
if (received.inputs[i].tick == 0) // empty input if (received.inputs[i].tick == 0) // empty input
continue; continue;
if(received.inputs[i].tick <= latest_tick) if (received.inputs[i].tick <= latest_tick)
continue; // don't reprocess inputs already processed continue; // don't reprocess inputs already processed
struct InputFrame cur_input = received.inputs[i]; struct InputFrame cur_input = received.inputs[i];
gs.players[player_slot].input.movement = cur_input.movement; gs.players[player_slot].input.movement = cur_input.movement;
@ -172,7 +141,7 @@ void server(void *data)
} }
if (cur_input.dobuild) if (cur_input.dobuild)
{ {
gs.players[player_slot].input.grid_index = cur_input.grid_index; gs.players[player_slot].input.grid_to_build_on = cur_input.grid_to_build_on;
gs.players[player_slot].input.build = cur_input.build; gs.players[player_slot].input.build = cur_input.build;
gs.players[player_slot].input.dobuild = cur_input.dobuild; gs.players[player_slot].input.dobuild = cur_input.dobuild;
gs.players[player_slot].input.build_type = cur_input.build_type; gs.players[player_slot].input.build_type = cur_input.build_type;
@ -234,6 +203,7 @@ void server(void *data)
} }
destroy(&gs); destroy(&gs);
free(entity_data);
enet_host_destroy(server); enet_host_destroy(server);
enet_deinitialize(); enet_deinitialize();
} }

@ -4,6 +4,9 @@ SendMode, Input
SetBatchLines, -1 SetBatchLines, -1
SetWorkingDir, %A_ScriptDir% SetWorkingDir, %A_ScriptDir%
; Fuck windows for having this hardcoded
^Esc::return
^b:: ^b::
WinKill, Flight WinKill, Flight
Sleep, 20 Sleep, 20

@ -1,12 +1,15 @@
#pragma once #pragma once
#define MAX_PLAYERS 4 #define MAX_PLAYERS 4
#define MAX_ENTITIES 1024
#define BOX_SIZE 0.25f #define BOX_SIZE 0.25f
#define PLAYER_SIZE ((V2){.x = BOX_SIZE, .y = BOX_SIZE})
#define PLAYER_MASS 0.5f
#define PLAYER_JETPACK_FORCE 1.0f
#define PLAYER_JETPACK_SPICE_PER_SECOND 0.1f
#define MAX_HAND_REACH 1.0f #define MAX_HAND_REACH 1.0f
#define GOLD_COLLECT_RADIUS 0.3f #define GOLD_COLLECT_RADIUS 0.3f
#define MAX_GRIDS 32
#define BUILD_BOX_SNAP_DIST_TO_SHIP 0.2f #define BUILD_BOX_SNAP_DIST_TO_SHIP 0.2f
#define MAX_BOXES_PER_GRID 32
#define BOX_MASS 1.0f #define BOX_MASS 1.0f
#define THRUSTER_FORCE 4.0f #define THRUSTER_FORCE 4.0f
#define THRUSTER_ENERGY_USED_PER_SECOND 0.05f #define THRUSTER_ENERGY_USED_PER_SECOND 0.05f
@ -68,6 +71,7 @@ enum BoxType
BoxHullpiece, BoxHullpiece,
BoxThruster, BoxThruster,
BoxBattery, BoxBattery,
BoxCockpit,
BoxLast, BoxLast,
}; };
@ -80,6 +84,13 @@ enum CompassRotation
RotationLast, RotationLast,
}; };
// when generation is 0, invalid ID
typedef struct
{
unsigned int generation; // if 0 then EntityID points to nothing, generation >= 1
unsigned int index; // index into the entity arena
} EntityID;
struct InputFrame struct InputFrame
{ {
uint64_t tick; uint64_t tick;
@ -91,15 +102,49 @@ struct InputFrame
bool dobuild; bool dobuild;
enum BoxType build_type; enum BoxType build_type;
enum CompassRotation build_rotation; enum CompassRotation build_rotation;
int grid_index; EntityID grid_to_build_on;
}; };
typedef struct Entity
{
bool exists;
EntityID next_free_entity;
unsigned int generation;
float damage; // used by box and player
cpBody *body; // used by grid, player, and box
cpShape *shape; // must be a box so shape_size can be set appropriately, and serialized
// for serializing the shape
EntityID shape_parent_entity; // can't be zero if shape is nonzero
V2 shape_size;
// player
bool is_player;
EntityID currently_piloting_seat;
float spice_taken_away; // at 1.0, out of spice
float goldness; // how much the player is a winner
// grids
bool is_grid;
float total_energy_capacity;
EntityID boxes;
// boxes
bool is_box;
enum BoxType box_type;
EntityID next_box;
EntityID prev_box; // doubly linked so can remove in middle of chain
enum CompassRotation compass_rotation;
float thrust; // must be between 0 and 1
float energy_used; // battery
} Entity;
// gotta update the serialization functions when this changes // gotta update the serialization functions when this changes
struct GameState typedef struct GameState
{ {
cpSpace *space; cpSpace *space;
uint64_t tick;
double time; double time;
V2 goldpos; V2 goldpos;
@ -107,43 +152,19 @@ struct GameState
struct Player struct Player
{ {
bool connected; bool connected;
EntityID entity;
int currently_inhabiting_index; // is equal to -1 when not inhabiting a grid
V2 pos;
V2 vel;
float spice_taken_away; // at 1.0, out of spice
float goldness; // how much the player is a winner
// input
// @Cleanup make this a frameinput struct instead of copying over all the fields like this
struct InputFrame input; struct InputFrame input;
} players[MAX_PLAYERS]; } players[MAX_PLAYERS];
// if body or shape is null, then that grid/box has been freed // Entity arena
// ent:ity pointers can't move around because of how the physics engine handles user data.
// important that this memory does not move around, each box shape in it has a pointer to its grid struct, stored in the box's shapes user_data // if you really need this, potentially refactor to store entity IDs instead of pointers
struct Grid // in the shapes and bodies of chipmunk. Would require editing the library I think
{ Entity *entities;
cpBody *body; int max_entities; // maximum number of entities possible in the entities list
float total_energy_capacity; // updated every frame by thruster logic int cur_next_entity; // next entity to pass on request of a new entity if the free list is empty
EntityID free_list;
struct Box } GameState;
{
enum BoxType type;
enum CompassRotation compass_rotation; // @Robust rename to compass_rotation
// thruster
float thrust; // must be between 0 and 1
// battery
float energy_used; // must be between 0 and 1
cpShape *shape;
float damage;
} boxes[MAX_BOXES_PER_GRID]; // @Robust this needs to be dynamically allocated, huge disparity in how many blocks a body can have...
} grids[MAX_GRIDS];
};
#define PI 3.14159f #define PI 3.14159f
@ -186,35 +207,44 @@ struct ClientToServer
void server(void *data); // data parameter required from thread api... void server(void *data); // data parameter required from thread api...
// gamestate // gamestate
void initialize(struct GameState *gs); // must do this to place boxes into it and process void initialize(struct GameState *gs, void *entity_arena, int entity_arena_size);
void destroy(struct GameState *gs); void destroy(struct GameState *gs);
void process(struct GameState *gs, float dt); // does in place void process(struct GameState *gs, float dt); // does in place
struct Grid *closest_to_point_in_radius(struct GameState *gs, V2 point, float radius); Entity *closest_to_point_in_radius(struct GameState *gs, V2 point, float radius);
uint64_t tick(struct GameState *gs); uint64_t tick(struct GameState *gs);
void into_bytes(struct ServerToClient *gs, char *out_bytes, int *out_len, int max_len); 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); void from_bytes(struct ServerToClient *gs, char *bytes, int max_len);
// entities
Entity *get_entity(struct GameState *gs, EntityID id);
Entity *new_entity(struct GameState *gs);
EntityID get_id(struct GameState *gs, Entity *e);
V2 entity_pos(Entity *e);
void entity_set_pos(Entity *e, V2 pos);
float entity_rotation(Entity *e);
#define BOX_CHAIN_ITER(gs, cur, starting_box) for (Entity *cur = get_entity(gs, starting_box); cur != NULL; cur = get_entity(gs, cur->next_box))
#define BOXES_ITER(gs, cur, grid_entity_ptr) BOX_CHAIN_ITER(gs, cur, (grid_entity_ptr)->boxes)
// player // player
void reset_player(struct Player *p); void player_destroy(struct Player *p);
void player_new(struct Player *p);
// grid // grid
void grid_new(struct Grid *to_modify, struct GameState *gs, V2 pos); void grid_create(struct GameState *gs, Entity *e);
V2 grid_com(struct Grid *grid); void box_create(struct GameState *gs, Entity *new_box, Entity *grid, V2 pos);
V2 grid_pos(struct Grid *grid); V2 grid_com(Entity *grid);
V2 grid_vel(struct Grid *grid); V2 grid_vel(Entity *grid);
V2 grid_local_to_world(struct Grid *grid, V2 local); V2 grid_local_to_world(Entity *grid, V2 local);
V2 grid_world_to_local(struct Grid *grid, V2 world); V2 grid_world_to_local(Entity *grid, V2 world);
V2 grid_snapped_box_pos(struct Grid *grid, V2 world); // returns the snapped pos in world coords V2 grid_snapped_box_pos(Entity *grid, V2 world); // returns the snapped pos in world coords
float grid_rotation(struct Grid *grid); float grid_angular_velocity(Entity *grid);
float grid_angular_velocity(struct Grid *grid); V2 entity_shape_pos(Entity *box);
void box_new(struct Box *to_modify, struct GameState *gs, struct Grid *grid, V2 pos); V2 box_pos(Entity *box);
V2 box_local_pos(struct Box *box); float box_rotation(Entity *box);
V2 box_pos(struct Box *box);
float box_rotation(struct Box *box);
// thruster // thruster
V2 thruster_direction(struct Box *box); V2 thruster_direction(Entity *box);
V2 thruster_force(struct Box *box); V2 thruster_force(Entity *box);
// debug draw // debug draw
void dbg_drawall(); void dbg_drawall();

Loading…
Cancel
Save