Make hand in local space sometimes again

- needed because world pos is incorrect wrt lag
main
Cameron Murphy Reikes 2 years ago
parent dcac22446e
commit bb063cf372

@ -229,6 +229,12 @@ void grid_create(GameState* gs, Entity* e)
create_body(gs, e); create_body(gs, e);
} }
void entity_set_rotation(Entity* e, float rot)
{
assert(e->body != NULL);
cpBodySetAngle(e->body, rot);
}
void entity_set_pos(Entity* e, V2 pos) void entity_set_pos(Entity* e, V2 pos)
{ {
assert(e->is_grid); assert(e->is_grid);
@ -676,7 +682,7 @@ void ser_entityid(SerState* ser, EntityID* id)
SER_VAR(&id->index); SER_VAR(&id->index);
} }
void ser_inputframe(SerState* ser, struct InputFrame* i) void ser_inputframe(SerState* ser, InputFrame* i)
{ {
SER_VAR(&i->tick); SER_VAR(&i->tick);
SER_VAR(&i->movement); SER_VAR(&i->movement);
@ -684,11 +690,11 @@ void ser_inputframe(SerState* ser, struct InputFrame* i)
SER_VAR(&i->seat_action); SER_VAR(&i->seat_action);
ser_entityid(ser, &i->seat_to_inhabit); ser_entityid(ser, &i->seat_to_inhabit);
SER_VAR(&i->hand_pos); SER_VAR(&i->hand_pos);
ser_entityid(ser, &i->grid_hand_pos_local_to);
SER_VAR(&i->dobuild); SER_VAR(&i->dobuild);
SER_VAR(&i->build_type); SER_VAR(&i->build_type);
SER_VAR(&i->build_rotation); SER_VAR(&i->build_rotation);
ser_entityid(ser, &i->grid_to_build_on);
} }
void ser_player(SerState* ser, Player* p) void ser_player(SerState* ser, Player* p)
@ -962,6 +968,18 @@ uint64_t tick(GameState* gs)
return (uint64_t)floor(gs->time / ((double)TIMESTEP)); return (uint64_t)floor(gs->time / ((double)TIMESTEP));
} }
V2 get_world_hand_pos(GameState* gs, InputFrame* input, Entity* player)
{
Entity* potential_grid = get_entity(gs, input->grid_hand_pos_local_to);
if (potential_grid != NULL)
{
return grid_local_to_world(potential_grid, input->hand_pos);
}
else {
return input->hand_pos;
}
}
void process(GameState* gs, float dt) void process(GameState* gs, float dt)
{ {
assert(gs->space != NULL); assert(gs->space != NULL);
@ -993,6 +1011,7 @@ void process(GameState* gs, float dt)
} }
#if 1 #if 1
V2 world_hand_pos = get_world_hand_pos(gs, &player->input, p);
if (player->input.seat_action) if (player->input.seat_action)
{ {
player->input.seat_action = false; // "handle" the input player->input.seat_action = false; // "handle" the input
@ -1000,7 +1019,7 @@ void process(GameState* gs, float dt)
if (the_seat == NULL) // not piloting any seat if (the_seat == NULL) // not piloting any seat
{ {
cpPointQueryInfo query_info = { 0 }; cpPointQueryInfo query_info = { 0 };
cpShape* result = cpSpacePointQueryNearest(gs->space, v2_to_cp(player->input.hand_pos), 0.1f, cpShapeFilterNew(CP_NO_GROUP, CP_ALL_CATEGORIES, BOXES), &query_info); cpShape* result = cpSpacePointQueryNearest(gs->space, v2_to_cp(world_hand_pos), 0.1f, cpShapeFilterNew(CP_NO_GROUP, CP_ALL_CATEGORIES, BOXES), &query_info);
if (result != NULL) if (result != NULL)
{ {
Entity* potential_seat = cp_shape_entity(result); Entity* potential_seat = cp_shape_entity(result);
@ -1013,7 +1032,8 @@ void process(GameState* gs, float dt)
} }
else else
{ {
Log("No ship above player at point %f %f\n", player->input.hand_pos.x, player->input.hand_pos.y);
Log("No ship above player at point %f %f\n", world_hand_pos.x, world_hand_pos.y);
} }
} }
else else
@ -1075,10 +1095,10 @@ void process(GameState* gs, float dt)
player->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... player->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 };
V2 world_build = player->input.hand_pos; V2 world_build = world_hand_pos;
// @Robust sanitize this input so player can't build on any grid in the world // @Robust sanitize this input so player can't build on any grid in the world
Entity* target_grid = get_entity(gs, player->input.grid_to_build_on); Entity* target_grid = get_entity(gs, player->input.grid_hand_pos_local_to);
cpShape* nearest = cpSpacePointQueryNearest(gs->space, v2_to_cp(world_build), 0.01f, cpShapeFilterNew(CP_NO_GROUP, CP_ALL_CATEGORIES, BOXES), &info); cpShape* nearest = cpSpacePointQueryNearest(gs->space, v2_to_cp(world_build), 0.01f, cpShapeFilterNew(CP_NO_GROUP, CP_ALL_CATEGORIES, BOXES), &info);
if (nearest != NULL) if (nearest != NULL)
{ {

@ -420,7 +420,7 @@ frame(void)
V2 grid_pos; V2 grid_pos;
float grid_rotation; float grid_rotation;
} build_preview = { 0 }; } build_preview = { 0 };
V2 hand_pos = { 0 }; V2 hand_pos = { 0 }; // in local space of grid when hovering over a grid
bool hand_at_arms_length = false; bool hand_at_arms_length = false;
{ {
// interpolate zoom // interpolate zoom
@ -439,6 +439,7 @@ frame(void)
// calculate build preview stuff // calculate build preview stuff
EntityID grid_to_build_on = (EntityID){ 0 }; EntityID grid_to_build_on = (EntityID){ 0 };
V2 possibly_local_hand_pos = (V2){ 0 };
if (myentity() != NULL) { if (myentity() != NULL) {
hand_pos = V2sub(world_mouse_pos, entity_pos(myentity())); hand_pos = V2sub(world_mouse_pos, entity_pos(myentity()));
float hand_len = V2length(hand_pos); float hand_len = V2length(hand_pos);
@ -452,6 +453,7 @@ frame(void)
hand_pos = V2scale(V2normalize(hand_pos), hand_len); hand_pos = V2scale(V2normalize(hand_pos), hand_len);
hand_pos = V2add(hand_pos, entity_pos(myentity())); hand_pos = V2add(hand_pos, entity_pos(myentity()));
possibly_local_hand_pos = hand_pos;
Entity* 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){
@ -462,6 +464,7 @@ frame(void)
else { else {
grid_to_build_on = get_id(&gs, placing_grid); grid_to_build_on = get_id(&gs, placing_grid);
hand_pos = grid_snapped_box_pos(placing_grid, hand_pos); hand_pos = grid_snapped_box_pos(placing_grid, hand_pos);
possibly_local_hand_pos = grid_world_to_local(placing_grid, hand_pos);
build_preview = (struct BuildPreviewInfo){ .grid_pos = entity_pos(placing_grid), build_preview = (struct BuildPreviewInfo){ .grid_pos = entity_pos(placing_grid),
.grid_rotation = entity_rotation(placing_grid), .grid_rotation = entity_rotation(placing_grid),
}; };
@ -474,7 +477,7 @@ frame(void)
// every frame // every frame
static size_t last_frame_id = 0; static size_t last_frame_id = 0;
struct InputFrame cur_input_frame = { 0 }; InputFrame cur_input_frame = { 0 };
cur_input_frame.id = last_frame_id; cur_input_frame.id = last_frame_id;
V2 input = (V2){ V2 input = (V2){
.x = (float)keydown[SAPP_KEYCODE_D] - (float)keydown[SAPP_KEYCODE_A], .x = (float)keydown[SAPP_KEYCODE_D] - (float)keydown[SAPP_KEYCODE_A],
@ -484,15 +487,16 @@ frame(void)
input = V2normalize(input); input = V2normalize(input);
cur_input_frame.movement = input; cur_input_frame.movement = input;
cur_input_frame.seat_action = keypressed[SAPP_KEYCODE_G].pressed; cur_input_frame.seat_action = keypressed[SAPP_KEYCODE_G].pressed;
cur_input_frame.hand_pos = hand_pos; cur_input_frame.grid_hand_pos_local_to = grid_to_build_on;
cur_input_frame.hand_pos = possibly_local_hand_pos;
if (mouse_pressed && cur_editing_boxtype != -1) { if (mouse_pressed && cur_editing_boxtype != -1) {
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_to_build_on = grid_to_build_on;
} }
struct InputFrame latest = client_to_server.inputs[0]; InputFrame latest = client_to_server.inputs[0];
// @Robust split this into separate lines and be very careful about testing for inequality // @Robust split this into separate lines and be very careful about testing for inequality
bool input_differs = false; bool input_differs = false;
@ -505,12 +509,12 @@ frame(void)
input_differs = input_differs || cur_input_frame.dobuild != latest.dobuild; input_differs = input_differs || cur_input_frame.dobuild != latest.dobuild;
input_differs = input_differs || cur_input_frame.build_type != latest.build_type; input_differs = input_differs || cur_input_frame.build_type != latest.build_type;
input_differs = input_differs || cur_input_frame.build_rotation != latest.build_rotation; input_differs = input_differs || cur_input_frame.build_rotation != latest.build_rotation;
input_differs = input_differs || !entityids_same(cur_input_frame.grid_to_build_on, latest.grid_to_build_on); input_differs = input_differs || !entityids_same(cur_input_frame.grid_hand_pos_local_to, latest.grid_hand_pos_local_to);
if (input_differs) { if (input_differs) {
struct InputFrame last_frame = client_to_server.inputs[0]; InputFrame last_frame = client_to_server.inputs[0];
for (int i = 0; i < INPUT_BUFFER - 1; i++) { for (int i = 0; i < INPUT_BUFFER - 1; i++) {
struct InputFrame last_last_frame = last_frame; InputFrame last_last_frame = last_frame;
last_frame = client_to_server.inputs[i + 1]; last_frame = client_to_server.inputs[i + 1];
client_to_server.inputs[i + 1] = last_last_frame; client_to_server.inputs[i + 1] = last_last_frame;
} }
@ -518,7 +522,6 @@ frame(void)
client_to_server.inputs[0] = cur_input_frame; client_to_server.inputs[0] = cur_input_frame;
last_frame_id += 1; last_frame_id += 1;
} }
dbg_rect(client_to_server.inputs[0].hand_pos);
static double last_input_sent_time = 0.0; static double last_input_sent_time = 0.0;
if (fabs(last_input_sent_time - time) > TIME_BETWEEN_INPUT_PACKETS) { if (fabs(last_input_sent_time - time) > TIME_BETWEEN_INPUT_PACKETS) {
@ -545,7 +548,8 @@ frame(void)
sgp_set_blend_mode(SGP_BLENDMODE_BLEND); sgp_set_blend_mode(SGP_BLENDMODE_BLEND);
// Draw background color // Draw background color
sgp_set_color(0.1f, 0.1f, 0.1f, 1.0f); set_color(colhexcode(0x020509));
// sgp_set_color(0.1f, 0.1f, 0.1f, 1.0f);
sgp_clear(); sgp_clear();
// sokol drawing library draw in world space // sokol drawing library draw in world space

@ -1,3 +1,4 @@
#include <chipmunk.h> // initializing bodies
#include "types.h" #include "types.h"
#include "sokol_time.h" #include "sokol_time.h"
#include <enet/enet.h> #include <enet/enet.h>
@ -5,6 +6,7 @@
#include <inttypes.h> // int64 printing #include <inttypes.h> // int64 printing
#include <stdlib.h> #include <stdlib.h>
// started in a thread from host // started in a thread from host
void server(void* data) void server(void* data)
{ {
@ -26,7 +28,24 @@ void server(void* data)
entity_set_pos(grid, (V2) { -BOX_SIZE * 2, 0.0f }); entity_set_pos(grid, (V2) { -BOX_SIZE * 2, 0.0f });
Entity* box = new_entity(&gs); Entity* box = new_entity(&gs);
box_create(&gs, box, grid, (V2) { 0 }); box_create(&gs, box, grid, (V2) { 0 });
}
// rotation test
if (false)
{
Entity* grid = new_entity(&gs);
grid_create(&gs, grid);
entity_set_pos(grid, (V2) { -BOX_SIZE * 2, 0.0f });
entity_set_rotation(grid, PI / 1.7f);
cpBodySetVelocity(grid->body, cpv(-0.1, 0.0));
cpBodySetAngularVelocity(grid->body, 1.0f);
#define BOX_AT(pos) { Entity* box = new_entity(&gs); box_create(&gs, box, grid, pos); }
BOX_AT(((V2) { 0 }));
BOX_AT(((V2) { BOX_SIZE, 0 }));
BOX_AT(((V2) { 2.0*BOX_SIZE, 0 }));
BOX_AT(((V2) { 2.0*BOX_SIZE, BOX_SIZE }));
BOX_AT(((V2) { 0.0*BOX_SIZE, -BOX_SIZE }));
} }
if (enet_initialize() != 0) if (enet_initialize() != 0)
@ -133,7 +152,7 @@ void server(void* data)
continue; continue;
if (received.inputs[i].id <= latest_id) if (received.inputs[i].id <= latest_id)
continue; // don't reprocess inputs already processed continue; // don't reprocess inputs already processed
struct InputFrame cur_input = received.inputs[i]; InputFrame cur_input = received.inputs[i];
gs.players[player_slot].input.movement = cur_input.movement; gs.players[player_slot].input.movement = cur_input.movement;
gs.players[player_slot].input.hand_pos = cur_input.hand_pos; gs.players[player_slot].input.hand_pos = cur_input.hand_pos;
@ -143,10 +162,11 @@ void server(void* data)
if (cur_input.seat_action) if (cur_input.seat_action)
{ {
gs.players[player_slot].input.seat_action = cur_input.seat_action; gs.players[player_slot].input.seat_action = cur_input.seat_action;
gs.players[player_slot].input.grid_hand_pos_local_to = cur_input.grid_hand_pos_local_to;
} }
if (cur_input.dobuild) if (cur_input.dobuild)
{ {
gs.players[player_slot].input.grid_to_build_on = cur_input.grid_to_build_on; gs.players[player_slot].input.grid_hand_pos_local_to = cur_input.grid_hand_pos_local_to;
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;
gs.players[player_slot].input.build_rotation = cur_input.build_rotation; gs.players[player_slot].input.build_rotation = cur_input.build_rotation;

@ -98,7 +98,7 @@ static bool entityids_same(EntityID a, EntityID b)
// when updated, must update serialization, AND comparison // when updated, must update serialization, AND comparison
// function in main.c // function in main.c
struct InputFrame typedef struct
{ {
uint64_t tick; uint64_t tick;
size_t id; // each input has unique, incrementing, I.D, so server doesn't double process inputs. Inputs to server should be ordered from 0-max like biggest id-smallest. This is done so if packet loss server still processes input size_t id; // each input has unique, incrementing, I.D, so server doesn't double process inputs. Inputs to server should be ordered from 0-max like biggest id-smallest. This is done so if packet loss server still processes input
@ -106,13 +106,13 @@ struct InputFrame
bool seat_action; bool seat_action;
EntityID seat_to_inhabit; EntityID seat_to_inhabit;
V2 hand_pos; // world coords, world star! V2 hand_pos;
EntityID grid_hand_pos_local_to; // when not null, hand_pos is local to this grid. this prevents bug where
bool dobuild; bool dobuild;
enum BoxType build_type; enum BoxType build_type;
enum CompassRotation build_rotation; enum CompassRotation build_rotation;
EntityID grid_to_build_on; } InputFrame;
};
typedef struct Entity typedef struct Entity
{ {
@ -158,7 +158,7 @@ typedef struct Player
{ {
bool connected; bool connected;
EntityID entity; EntityID entity;
struct InputFrame input; InputFrame input;
} Player; } Player;
// gotta update the serialization functions when this changes // gotta update the serialization functions when this changes
typedef struct GameState typedef struct GameState
@ -215,7 +215,7 @@ typedef struct ServerToClient
struct ClientToServer struct ClientToServer
{ {
struct InputFrame inputs[INPUT_BUFFER]; InputFrame inputs[INPUT_BUFFER];
}; };
// server // server
@ -235,6 +235,7 @@ Entity* get_entity(struct GameState* gs, EntityID id);
Entity* new_entity(struct GameState* gs); Entity* new_entity(struct GameState* gs);
EntityID get_id(struct GameState* gs, Entity* e); EntityID get_id(struct GameState* gs, Entity* e);
V2 entity_pos(Entity* e); V2 entity_pos(Entity* e);
void entity_set_rotation(Entity* e, float rot);
void entity_set_pos(Entity* e, V2 pos); void entity_set_pos(Entity* e, V2 pos);
float entity_rotation(Entity* e); 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 BOX_CHAIN_ITER(gs, cur, starting_box) for (Entity *cur = get_entity(gs, starting_box); cur != NULL; cur = get_entity(gs, cur->next_box))
@ -409,6 +410,15 @@ static Color colhex(int r, int g, int b)
}; };
} }
static Color colhexcode(int hexcode)
{
// 0x020509;
int r = (hexcode >> 16) & 0xFF;
int g = (hexcode >> 8) & 0xFF;
int b = (hexcode >> 0) & 0xFF;
return colhex(r, g, b);
}
static Color Collerp(Color a, Color b, float factor) static Color Collerp(Color a, Color b, float factor)
{ {
Color to_return = { 0 }; Color to_return = { 0 };

Loading…
Cancel
Save