Thruster placing/rotate, toolbar UI

main
Cameron Murphy Reikes 2 years ago
parent 4d147e77de
commit 547727c7f3

@ -367,6 +367,30 @@ void des_grid(char **in, struct Grid *g, struct GameState *gs)
} }
} }
void ser_inputframe(char **out, struct InputFrame *i)
{
ser_V2(out, i->movement);
ser_bool(out, i->inhabit);
ser_V2(out, i->build);
ser_bool(out, i->dobuild);
ser_int(out, i->build_type);
ser_int(out, i->build_rotation);
ser_int(out, i->grid_index);
}
void des_inputframe(char **in, struct InputFrame *i)
{
des_V2(in, &i->movement);
des_bool(in, &i->inhabit);
des_V2(in, &i->build);
des_bool(in, &i->dobuild);
des_int(in, (int *)&i->build_type);
des_int(in, (int *)&i->build_rotation);
des_int(in, &i->grid_index);
}
void ser_player(char **out, struct Player *p) void ser_player(char **out, struct Player *p)
{ {
ser_bool(out, p->connected); ser_bool(out, p->connected);
@ -378,13 +402,7 @@ void ser_player(char **out, struct Player *p)
ser_float(out, p->spice_taken_away); ser_float(out, p->spice_taken_away);
ser_float(out, p->goldness); ser_float(out, p->goldness);
// input ser_inputframe(out, &p->input);
ser_V2(out, p->movement);
ser_bool(out, p->inhabit);
ser_V2(out, p->build);
ser_bool(out, p->dobuild);
ser_int(out, p->grid_index);
} }
} }
@ -399,13 +417,7 @@ void des_player(char **in, struct Player *p, struct GameState *gs)
des_float(in, &p->spice_taken_away); des_float(in, &p->spice_taken_away);
des_float(in, &p->goldness); des_float(in, &p->goldness);
// input des_inputframe(in, &p->input);
des_V2(in, &p->movement);
des_bool(in, &p->inhabit);
des_V2(in, &p->build);
des_bool(in, &p->dobuild);
des_int(in, &p->grid_index);
} }
} }
@ -586,9 +598,9 @@ void process(struct GameState *gs, float dt)
p->currently_inhabiting_index = -1; p->currently_inhabiting_index = -1;
} }
if (p->inhabit) if (p->input.inhabit)
{ {
p->inhabit = false; // "handle" the input p->input.inhabit = false; // "handle" the input
if (p->currently_inhabiting_index == -1) if (p->currently_inhabiting_index == -1)
{ {
@ -644,15 +656,15 @@ void process(struct GameState *gs, float dt)
// process movement // process movement
{ {
// no cheating by making movement bigger than length 1 // no cheating by making movement bigger than length 1
if (V2length(p->movement) != 0.0f) if (V2length(p->input.movement) != 0.0f)
{ {
p->movement = V2scale(V2normalize(p->movement), clamp(V2length(p->movement), 0.0f, 1.0f)); p->input.movement = V2scale(V2normalize(p->input.movement), clamp(V2length(p->input.movement), 0.0f, 1.0f));
} }
if (p->currently_inhabiting_index == -1) if (p->currently_inhabiting_index == -1)
{ {
// @Robust make sure movement vector is normalized so player can't cheat // @Robust make sure movement vector is normalized so player can't cheat
p->vel = V2add(p->vel, V2scale(p->movement, dt * 0.5f)); p->vel = V2add(p->vel, V2scale(p->input.movement, dt * 0.5f));
p->spice_taken_away += dt * 0.15f * V2length(p->movement); p->spice_taken_away += dt * 0.15f * V2length(p->input.movement);
} }
else else
{ {
@ -664,9 +676,9 @@ void process(struct GameState *gs, float dt)
float thruster_spice_consumption = 0.0f; float thruster_spice_consumption = 0.0f;
{ {
V2 target_direction = {0}; V2 target_direction = {0};
if (V2length(p->movement) > 0.0f) if (V2length(p->input.movement) > 0.0f)
{ {
target_direction = V2normalize(p->movement); target_direction = V2normalize(p->input.movement);
} }
for (int ii = 0; ii < MAX_BOXES_PER_GRID; ii++) for (int ii = 0; ii < MAX_BOXES_PER_GRID; ii++)
{ {
@ -681,23 +693,23 @@ void process(struct GameState *gs, float dt)
} }
} }
// 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->input.movement, 5.0f)), v2_to_cp(grid_com(g)));
// bigger the ship, the more efficient the spice usage // bigger the ship, the more efficient the spice usage
p->spice_taken_away += dt * thruster_spice_consumption * THRUSTER_SPICE_PER_SECOND; p->spice_taken_away += dt * thruster_spice_consumption * THRUSTER_SPICE_PER_SECOND;
} }
p->pos = V2add(p->pos, V2scale(p->vel, dt)); p->pos = V2add(p->pos, V2scale(p->vel, dt));
} }
if (p->dobuild) if (p->input.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... p->input.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}; cpPointQueryInfo info = {0};
// @Robust make sure to query only against boxes... // @Robust make sure to query only against boxes...
V2 world_build = p->build; V2 world_build = p->input.build;
if (p->grid_index != -1) if (p->input.grid_index != -1)
{ {
world_build = grid_local_to_world(&gs->grids[p->grid_index], p->build); world_build = grid_local_to_world(&gs->grids[p->input.grid_index], p->input.build);
} }
cpShape *nearest = cpSpacePointQueryNearest(gs->space, v2_to_cp(world_build), 0.01f, cpShapeFilterNew(CP_NO_GROUP, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES), &info); cpShape *nearest = cpSpacePointQueryNearest(gs->space, v2_to_cp(world_build), 0.01f, cpShapeFilterNew(CP_NO_GROUP, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES), &info);
if (nearest != NULL) if (nearest != NULL)
@ -707,7 +719,7 @@ void process(struct GameState *gs, float dt)
grid_remove_box(gs->space, cur_grid, cur_box); grid_remove_box(gs->space, cur_grid, cur_box);
p->spice_taken_away -= 0.1f; p->spice_taken_away -= 0.1f;
} }
else if (p->grid_index == -1) else if (p->input.grid_index == -1)
{ {
// @Robust better memory mgmt // @Robust better memory mgmt
struct Grid *empty_grid = NULL; struct Grid *empty_grid = NULL;
@ -719,15 +731,18 @@ void process(struct GameState *gs, float dt)
break; break;
} }
} }
// @Robust cleanly fail when not enough grids
assert(empty_grid != NULL); assert(empty_grid != NULL);
p->spice_taken_away += 0.2f; p->spice_taken_away += 0.2f;
grid_new(empty_grid, gs, world_build); grid_new(empty_grid, gs, world_build);
box_new(&empty_grid->boxes[0], gs, empty_grid, (V2){0}); box_new(&empty_grid->boxes[0], gs, empty_grid, (V2){0});
empty_grid->boxes[0].type = p->input.build_type;
empty_grid->boxes[0].rotation = p->input.build_rotation;
cpBodySetVelocity(empty_grid->body, v2_to_cp(p->vel)); cpBodySetVelocity(empty_grid->body, v2_to_cp(p->vel));
} }
else else
{ {
struct Grid *g = &gs->grids[p->grid_index]; struct Grid *g = &gs->grids[p->input.grid_index];
struct Box *empty_box = NULL; struct Box *empty_box = NULL;
for (int ii = 0; ii < MAX_BOXES_PER_GRID; ii++) for (int ii = 0; ii < MAX_BOXES_PER_GRID; ii++)
@ -742,6 +757,8 @@ void process(struct GameState *gs, float dt)
assert(empty_box != NULL); assert(empty_box != NULL);
p->spice_taken_away += 0.1f; p->spice_taken_away += 0.1f;
box_new(empty_box, gs, g, grid_world_to_local(g, world_build)); box_new(empty_box, gs, g, grid_world_to_local(g, world_build));
empty_box->type = p->input.build_type;
empty_box->rotation = p->input.build_rotation;
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

313
main.c

@ -39,8 +39,37 @@ static ENetHost *client;
static ENetPeer *peer; static ENetPeer *peer;
static float zoom_target = 300.0f; static float zoom_target = 300.0f;
static float zoom = 300.0f; static float zoom = 300.0f;
static sg_image image_hullpiece; static sg_image image_itemframe;
static sg_image image_thruster; static sg_image image_itemframe_selected;
static int cur_editing_boxtype = -1;
static int cur_editing_rotation = 0;
static struct BoxInfo
{
enum BoxType type;
const char *image_path;
sg_image image;
} boxes[] = { // if added to here will show up in toolbar, is placeable
{
.type = BoxHullpiece,
.image_path = "loaded/hullpiece.png",
},
{
.type = BoxThruster,
.image_path = "loaded/thruster.png",
}};
const int boxes_len = sizeof(boxes) / sizeof(*boxes);
struct BoxInfo boxinfo(enum BoxType type)
{
for (int i = 0; i < boxes_len; i++)
{
if (boxes[i].type == type)
return boxes[i];
}
Log("No box info found for type %d\n", type);
return (struct BoxInfo){0};
}
static sg_image load_image(const char *path) static sg_image load_image(const char *path)
{ {
@ -96,8 +125,12 @@ static void init(void)
// image loading // image loading
{ {
image_hullpiece = load_image("loaded/hullpiece.png"); for (int i = 0; i < boxes_len; i++)
image_thruster = load_image("loaded/thruster.png"); {
boxes[i].image = load_image(boxes[i].image_path);
}
image_itemframe = load_image("loaded/itemframe.png");
image_itemframe_selected = load_image("loaded/itemframe_selected.png");
} }
// socket initialization // socket initialization
@ -153,20 +186,9 @@ static void drawbox(V2 boxpos, float rot, float damage, enum BoxType type, enum
float halfbox = BOX_SIZE / 2.0f; float halfbox = BOX_SIZE / 2.0f;
sgp_push_transform(); sgp_push_transform();
sgp_rotate_at(rot, boxpos.x, boxpos.y); sgp_rotate_at(rot, boxpos.x, boxpos.y);
switch(type) sgp_set_image(0, boxinfo(type).image);
{ sgp_rotate_at(rotangle(rotation), boxpos.x, boxpos.y);
case BoxHullpiece:
sgp_set_image(0, image_hullpiece);
break;
case BoxThruster:
sgp_set_image(0, image_thruster);
break;
default:
Log("Unknown image for box type of type %d\n", type);
break;
}
sgp_rotate_at( rotangle(rotation),boxpos.x,boxpos.y);
sgp_draw_textured_rect(boxpos.x - halfbox, boxpos.y - halfbox, BOX_SIZE, BOX_SIZE); sgp_draw_textured_rect(boxpos.x - halfbox, boxpos.y - halfbox, BOX_SIZE, BOX_SIZE);
sgp_reset_image(0); sgp_reset_image(0);
@ -202,6 +224,69 @@ 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)
{
// draw spice bar
if (draw && myplayer != -1)
{
sgp_set_color(0.5f, 0.5f, 0.5f, 1.0f);
float margin = width * 0.1;
float bar_width = width - margin * 2.0f;
sgp_draw_filled_rect(margin, 80.0f, bar_width, 30.0f);
sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f);
sgp_draw_filled_rect(margin, 80.0f, bar_width * (1.0f - gs.players[myplayer].spice_taken_away), 30.0f);
}
// draw item toolbar
{
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 total_width = itemframe_width * boxes_len;
float item_width = itemframe_width * 0.75;
float item_height = itemframe_height * 0.75;
float item_offset_x = (itemframe_width - item_width) / 2.0f;
float item_offset_y = (itemframe_height - item_height) / 2.0f;
float x = width / 2.0 - total_width / 2.0;
float y = height - itemframe_height * 1.5;
for (int i = 0; i < boxes_len; i++)
{
if (has_point((AABB){
.x = x,
.y = y,
.width = itemframe_width,
.height = itemframe_height,
},
mouse_pos) &&
mouse_pressed)
{
// "handle" mouse pressed
mouse_pressed = false;
cur_editing_boxtype = i;
}
if (draw)
{
sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f);
if (cur_editing_boxtype == i)
{
sgp_set_image(0, image_itemframe_selected);
}
else
{
sgp_set_image(0, image_itemframe);
}
sgp_draw_textured_rect(x, y, itemframe_width, itemframe_height);
sgp_set_image(0, boxinfo((enum BoxType)i).image);
sgp_draw_textured_rect(x + item_offset_x, y + item_offset_y, item_width, item_height);
sgp_reset_image(0);
}
x += itemframe_width;
}
}
}
static void frame(void) static void frame(void)
{ {
int width = sapp_width(), height = sapp_height(); int width = sapp_width(), height = sapp_height();
@ -269,6 +354,7 @@ static void frame(void)
} }
// gameplay // gameplay
ui(false, 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}; V2 camera_pos = {0};
@ -356,6 +442,8 @@ static void frame(void)
cur_input_frame.grid_index = grid_index; cur_input_frame.grid_index = grid_index;
if (cur_input_frame.dobuild) if (cur_input_frame.dobuild)
{ {
cur_input_frame.build_type = cur_editing_boxtype;
cur_input_frame.build_rotation = cur_editing_rotation;
if (grid_index != -1) if (grid_index != -1)
{ {
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(&gs.grids[cur_input_frame.grid_index], build_preview.pos);
@ -410,122 +498,119 @@ static void frame(void)
sgp_set_color(0.1f, 0.1f, 0.1f, 1.0f); sgp_set_color(0.1f, 0.1f, 0.1f, 1.0f);
sgp_clear(); sgp_clear();
// draw spice bar
if (myplayer != -1)
{
sgp_set_color(0.5f, 0.5f, 0.5f, 1.0f);
float margin = width * 0.1;
float bar_width = width - margin * 2.0f;
sgp_draw_filled_rect(margin, 80.0f, bar_width, 30.0f);
sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f);
sgp_draw_filled_rect(margin, 80.0f, bar_width * (1.0f - gs.players[myplayer].spice_taken_away), 30.0f);
}
// 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
{ {
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);
// camera go to player // camera go to player
sgp_translate(-camera_pos.x, -camera_pos.y); sgp_translate(-camera_pos.x, -camera_pos.y);
}
if (myplayer != -1) // hand reached limit circle
{ if (myplayer != -1)
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); static float hand_reach_alpha = 1.0f;
sgp_set_color(1.0f, 1.0f, 1.0f, hand_reach_alpha); hand_reach_alpha = lerp(hand_reach_alpha, hand_at_arms_length ? 1.0f : 0.0f, dt * 5.0);
draw_circle(gs.players[myplayer].pos, MAX_HAND_REACH); sgp_set_color(1.0f, 1.0f, 1.0f, hand_reach_alpha);
} draw_circle(gs.players[myplayer].pos, 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 = 50;
for (int x = -num; x < num; x++) for (int x = -num; x < num; x++)
{
for (int y = -num; y < num; y++)
{ {
sgp_draw_point((float)x * 0.1f, (float)y * 0.1f); for (int y = -num; y < num; y++)
{
sgp_draw_point((float)x * 0.1f, (float)y * 0.1f);
}
} }
}
float halfbox = BOX_SIZE / 2.0f; float halfbox = BOX_SIZE / 2.0f;
// mouse // mouse
if (mouse_frozen) if (mouse_frozen)
{ {
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);
} }
// building preview // building preview
{ if(cur_editing_boxtype != -1){
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(build_preview.pos, build_preview.grid_rotation, 0.0f, BoxHullpiece, Right); drawbox(build_preview.pos, build_preview.grid_rotation, 0.0f, cur_editing_boxtype, cur_editing_rotation);
} }
// grids // grids
{
for (int i = 0; i < MAX_GRIDS; i++)
{ {
SKIPNULL(gs.grids[i].body); for (int i = 0; i < MAX_GRIDS; i++)
struct Grid *g = &gs.grids[i];
for (int ii = 0; ii < MAX_BOXES_PER_GRID; ii++)
{ {
SKIPNULL(g->boxes[ii].shape); SKIPNULL(gs.grids[i].body);
struct Box *b = &g->boxes[ii]; struct Grid *g = &gs.grids[i];
sgp_set_color(0.5f, 0.5f, 0.5f, 1.0f); for (int ii = 0; ii < MAX_BOXES_PER_GRID; ii++)
// debug draw force vectors for thrusters {
if (false){ SKIPNULL(g->boxes[ii].shape);
if(b->type == BoxThruster) { struct Box *b = &g->boxes[ii];
dbg_rect(box_pos(b)); sgp_set_color(0.5f, 0.5f, 0.5f, 1.0f);
dbg_line(box_pos(b), V2add(box_pos(b), V2scale(thruster_force(b), -1.0f))); // debug draw force vectors for thrusters
if (false)
{
if (b->type == BoxThruster)
{
dbg_rect(box_pos(b));
dbg_line(box_pos(b), V2add(box_pos(b), V2scale(thruster_force(b), -1.0f)));
}
} }
drawbox(box_pos(b), grid_rotation(g), b->damage, b->type, b->rotation);
} }
drawbox(box_pos(b), grid_rotation(g), b->damage, b->type, b->rotation); sgp_set_color(1.0f, 0.0f, 0.0f, 1.0f);
V2 vel = grid_vel(&gs.grids[i]);
V2 to = V2add(grid_com(g), vel);
sgp_draw_line(grid_com(g).x, grid_com(g).y, to.x, to.y);
} }
sgp_set_color(1.0f, 0.0f, 0.0f, 1.0f);
V2 vel = grid_vel(&gs.grids[i]);
V2 to = V2add(grid_com(g), vel);
sgp_draw_line(grid_com(g).x, grid_com(g).y, to.x, to.y);
} }
}
// player // player
for (int i = 0; i < MAX_PLAYERS; i++) for (int i = 0; i < MAX_PLAYERS; i++)
{ {
struct Player *p = &gs.players[i]; struct Player *p = &gs.players[i];
if (!p->connected) if (!p->connected)
continue; continue;
static float opacities[MAX_PLAYERS] = {1.0f}; static float opacities[MAX_PLAYERS] = {1.0f};
opacities[i] = lerp(opacities[i], p->currently_inhabiting_index == -1 ? 1.0f : 0.1f, dt * 7.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); Color col_to_draw = Collerp(WHITE, GOLD, p->goldness);
col_to_draw.a = opacities[i]; col_to_draw.a = opacities[i];
set_color(col_to_draw); set_color(col_to_draw);
sgp_push_transform(); sgp_push_transform();
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(p->pos.x - psize / 2.0f, p->pos.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(); 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 // UI drawn in screen space
set_color(GOLD); ui(true, width, height);
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();
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);
@ -553,6 +638,18 @@ void event(const sapp_event *e)
{ {
mouse_frozen = !mouse_frozen; mouse_frozen = !mouse_frozen;
} }
if (e->key_code == SAPP_KEYCODE_R)
{
cur_editing_rotation += 1;
cur_editing_rotation %= RotationLast;
}
int key_num = e->key_code - SAPP_KEYCODE_0;
int target_box = key_num - 1;
if(target_box < BoxLast)
{
cur_editing_boxtype = target_box;
}
if (!mouse_frozen) if (!mouse_frozen)
{ {
keydown[e->key_code] = true; keydown[e->key_code] = true;

@ -157,20 +157,22 @@ void server(void *data)
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].movement = cur_input.movement; gs.players[player_slot].input.movement = cur_input.movement;
gs.players[player_slot].grid_index = cur_input.grid_index; gs.players[player_slot].input.grid_index = cur_input.grid_index;
// for these "event" inputs, only modify the game state if the event is true. // for these "event" inputs, only modify the current input if the event is true.
// while processing the gamestate, will mark it as false once processed. This // while processing the gamestate, will mark it as false once processed. This
// prevents setting the event input to false before it's been processed. // prevents setting the event input to false before it's been processed.
if (cur_input.inhabit) if (cur_input.inhabit)
{ {
gs.players[player_slot].inhabit = cur_input.inhabit; gs.players[player_slot].input.inhabit = cur_input.inhabit;
} }
if (cur_input.dobuild) if (cur_input.dobuild)
{ {
gs.players[player_slot].build = cur_input.build; gs.players[player_slot].input.build = cur_input.build;
gs.players[player_slot].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_rotation = cur_input.build_rotation;
} }
} }
player_to_latest_tick_processed[player_slot] = received.inputs[0].tick; player_to_latest_tick_processed[player_slot] = received.inputs[0].tick;

@ -8,8 +8,8 @@
#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 MAX_BOXES_PER_GRID 32
#define BOX_MASS 1.0f #define BOX_MASS 1.0f
#define THRUSTER_FORCE 2.0f #define THRUSTER_FORCE 4.0f
#define THRUSTER_SPICE_PER_SECOND 0.1f #define THRUSTER_SPICE_PER_SECOND 0.02f
#define TIMESTEP (1.0f / 60.0f) // not required to simulate at this, but this defines what tick the game is on #define TIMESTEP (1.0f / 60.0f) // not required to simulate at this, but this defines what tick the game is on
#define TIME_BETWEEN_INPUT_PACKETS (1.0f / 20.0f) #define TIME_BETWEEN_INPUT_PACKETS (1.0f / 20.0f)
@ -22,7 +22,7 @@
// @Robust remove this include somehow, needed for sqrt and cos // @Robust remove this include somehow, needed for sqrt and cos
#include <math.h> #include <math.h>
#include <stdint.h> // tick is unsigned integer #include <stdint.h> // tick is unsigned integer
#include <stdio.h> // logging on errors for functions #include <stdio.h> // logging on errors for functions
// including headers from headers bad // including headers from headers bad
#ifndef SOKOL_GP_INCLUDED #ifndef SOKOL_GP_INCLUDED
@ -63,6 +63,36 @@ typedef sgp_point P2;
fprintf(stdout, "%s:%d | ", __FILE__, __LINE__); \ fprintf(stdout, "%s:%d | ", __FILE__, __LINE__); \
fprintf(stdout, __VA_ARGS__) fprintf(stdout, __VA_ARGS__)
enum BoxType
{
BoxHullpiece,
BoxThruster,
BoxLast
};
enum Rotation
{
Right,
Down,
Left,
Up,
RotationLast,
};
struct InputFrame
{
uint64_t tick;
V2 movement;
bool inhabit;
// if grid_index != -1, this is in local coordinates to the grid
V2 build;
bool dobuild;
enum BoxType build_type;
enum Rotation build_rotation;
int grid_index;
};
// gotta update the serialization functions when this changes // gotta update the serialization functions when this changes
struct GameState struct GameState
{ {
@ -86,13 +116,7 @@ struct GameState
// input // input
// @Cleanup make this a frameinput struct instead of copying over all the fields like this // @Cleanup make this a frameinput struct instead of copying over all the fields like this
V2 movement; // can be at maximum length 1.0 struct InputFrame input;
bool inhabit;
// if grid_index != -1, this is in local coordinates to the grid
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
@ -104,19 +128,9 @@ struct GameState
struct Box struct Box
{ {
enum BoxType enum BoxType type;
{ enum Rotation rotation;
BoxHullpiece,
BoxThruster,
} type;
enum Rotation
{
Right,
Down,
Left,
Up,
} rotation;
// thruster // thruster
float thrust; // must be between 0 and 1 float thrust; // must be between 0 and 1
@ -131,24 +145,24 @@ struct GameState
// returns in radians // returns in radians
static float rotangle(enum Rotation rot) static float rotangle(enum Rotation rot)
{ {
switch(rot) switch (rot)
{ {
case Right: case Right:
return 0.0f; return 0.0f;
break; break;
case Down: case Down:
return -PI/2.0f; return -PI / 2.0f;
break; break;
case Left: case Left:
return -PI; return -PI;
break; break;
case Up: case Up:
return -3.0f * PI/2.0f; return -3.0f * PI / 2.0f;
break; break;
default: default:
Log("Unknown rotation %d\n", rot); Log("Unknown rotation %d\n", rot);
return -0.0f; return -0.0f;
break; break;
} }
} }
@ -160,17 +174,7 @@ struct ServerToClient
struct ClientToServer struct ClientToServer
{ {
struct InputFrame struct InputFrame inputs[INPUT_BUFFER];
{
uint64_t tick;
V2 movement;
bool inhabit;
// if grid_index != -1, this is in local coordinates to the grid
V2 build;
bool dobuild;
int grid_index;
} inputs[INPUT_BUFFER];
}; };
// server // server
@ -218,6 +222,15 @@ void dbg_rect(V2 center);
// all the math is static so that it can be defined in each compilation unit its included in // all the math is static so that it can be defined in each compilation unit its included in
typedef struct AABB
{
float x, y, width, height;
} AABB;
static bool has_point(AABB aabb, V2 point)
{
return point.x > aabb.x && point.x < aabb.x + aabb.width && point.y > aabb.y && point.y < aabb.y + aabb.height;
}
static V2 V2add(V2 a, V2 b) static V2 V2add(V2 a, V2 b)
{ {

Loading…
Cancel
Save