Change all gamestate to double precision floats

main
Cameron Murphy Reikes 2 years ago
parent 72e36e9b3d
commit d8bfe6d879

@ -1 +1,2 @@
thirdparty/ thirdparty/opus/
thirdparty/minilzo/

@ -0,0 +1,22 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"windowsSdkVersion": "10.0.22000.0",
"compilerPath": "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.33.31629/bin/Hostx64/x64/cl.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "windows-msvc-x64",
"compileCommands": "${workspaceFolder}/compile_commands.json"
}
],
"version": 4
}

@ -42,21 +42,21 @@ void dbg_drawall()
sgp_set_color(0.4f, 0.8f, 0.2f, 0.8f); sgp_set_color(0.4f, 0.8f, 0.2f, 0.8f);
for (int i = 0; i < command_i; i++) for (int i = 0; i < command_i; i++)
{ {
const float size = 0.05f; const double size = 0.05;
switch (commands[i].type) switch (commands[i].type)
{ {
case rect: case rect:
{ {
V2 center = commands[i].center; V2 center = commands[i].center;
V2 upper_left = V2add(center, (V2){.x = -size / 2.0f, .y = -size / 2.0f}); V2 upper_left = V2add(center, (V2){.x = -size / 2.0, .y = -size / 2.0});
sgp_draw_filled_rect(upper_left.x, upper_left.y, size, size); sgp_draw_filled_rect((float)upper_left.x, (float)upper_left.y, (float)size, (float)size);
break; break;
} }
case line: case line:
{ {
V2 from = commands[i].from; V2 from = commands[i].from;
V2 to = commands[i].to; V2 to = commands[i].to;
sgp_draw_line(from.x, from.y, to.x, to.y); sgp_draw_line((float)from.x, (float)from.y, (float)to.x, (float)to.y);
break; break;
} }
} }

@ -83,7 +83,7 @@ bool cloaking_active(GameState *gs, Entity *e)
{ {
// cloaking doesn't work for first 1/2 second of game because when initializing // cloaking doesn't work for first 1/2 second of game because when initializing
// everything needs to be uncloaked // everything needs to be uncloaked
return gs->time >= 0.5 && (gs->time - e->time_was_last_cloaked) <= TIMESTEP * 2.0f; return gs->time >= 0.5 && (gs->time - e->time_was_last_cloaked) <= TIMESTEP * 2.0;
} }
bool is_cloaked(GameState *gs, Entity *e, Entity *this_players_perspective) bool is_cloaked(GameState *gs, Entity *e, Entity *this_players_perspective)
@ -219,8 +219,8 @@ V2 entity_vel(GameState *gs, Entity *e)
return (V2){0}; return (V2){0};
} }
static THREADLOCAL float to_face = 0.0f; static THREADLOCAL double to_face = 0.0;
static THREADLOCAL float nearest_dist = INFINITY; static THREADLOCAL double nearest_dist = INFINITY;
static THREADLOCAL bool target_found = false; static THREADLOCAL bool target_found = false;
static void on_missile_shape(cpShape *shape, cpContactPointSet *points, void *data) static void on_missile_shape(cpShape *shape, cpContactPointSet *points, void *data)
{ {
@ -243,9 +243,9 @@ static void on_missile_shape(cpShape *shape, cpContactPointSet *points, void *da
// lookahead by their velocity // lookahead by their velocity
V2 rel_velocity = V2sub(entity_vel(gs, other), entity_vel(gs, launcher)); V2 rel_velocity = V2sub(entity_vel(gs, other), entity_vel(gs, launcher));
float dist = V2dist(entity_pos(other), entity_pos(launcher)); double dist = V2dist(entity_pos(other), entity_pos(launcher));
float time_of_travel = sqrtf((2.0f * dist) / (MISSILE_BURN_FORCE / MISSILE_MASS)); double time_of_travel = sqrt((2.0 * dist) / (MISSILE_BURN_FORCE / MISSILE_MASS));
V2 other_future_pos = V2add(entity_pos(other), V2scale(rel_velocity, time_of_travel)); V2 other_future_pos = V2add(entity_pos(other), V2scale(rel_velocity, time_of_travel));
@ -257,13 +257,13 @@ static void on_missile_shape(cpShape *shape, cpContactPointSet *points, void *da
LauncherTarget missile_launcher_target(GameState *gs, Entity *launcher) LauncherTarget missile_launcher_target(GameState *gs, Entity *launcher)
{ {
to_face = 0.0f; to_face = 0.0;
cpBody *tmp = cpBodyNew(0.0f, 0.0f); cpBody *tmp = cpBodyNew(0.0, 0.0);
cpBodySetPosition(tmp, v2_to_cp(entity_pos(launcher))); cpBodySetPosition(tmp, v2_to_cp(entity_pos(launcher)));
cpShape *circle = cpCircleShapeNew(tmp, MISSILE_RANGE, cpv(0, 0)); cpShape *circle = cpCircleShapeNew(tmp, MISSILE_RANGE, cpv(0, 0));
nearest_dist = INFINITY; nearest_dist = INFINITY;
to_face = 0.0f; to_face = 0.0;
target_found = false; target_found = false;
cpSpaceShapeQuery(gs->space, circle, on_missile_shape, (void *)launcher); cpSpaceShapeQuery(gs->space, circle, on_missile_shape, (void *)launcher);
@ -348,7 +348,7 @@ Entity *new_entity(GameState *gs)
} }
// pos, mass, radius // pos, mass, radius
EntityID create_sun(GameState *gs, Entity *new_sun, V2 pos, V2 vel, float mass, float radius) EntityID create_sun(GameState *gs, Entity *new_sun, V2 pos, V2 vel, double mass, double radius)
{ {
assert(new_sun != NULL); assert(new_sun != NULL);
new_sun->is_sun = true; new_sun->is_sun = true;
@ -401,7 +401,7 @@ void grid_create(GameState *gs, Entity *e)
create_body(gs, e); create_body(gs, e);
} }
void entity_set_rotation(Entity *e, float rot) void entity_set_rotation(Entity *e, double rot)
{ {
assert(e->body != NULL); assert(e->body != NULL);
cpBodySetAngle(e->body, rot); cpBodySetAngle(e->body, rot);
@ -415,7 +415,7 @@ void entity_set_pos(Entity *e, V2 pos)
} }
// size is (1/2 the width, 1/2 the height) // size is (1/2 the width, 1/2 the height)
void create_rectangle_shape(GameState *gs, Entity *e, Entity *parent, V2 pos, V2 size, float mass) void create_rectangle_shape(GameState *gs, Entity *e, Entity *parent, V2 pos, V2 size, double mass)
{ {
if (e->shape != NULL) if (e->shape != NULL)
{ {
@ -434,7 +434,7 @@ void create_rectangle_shape(GameState *gs, Entity *e, Entity *parent, V2 pos, V2
e->shape_size = size; e->shape_size = size;
e->shape_parent_entity = get_id(gs, parent); e->shape_parent_entity = get_id(gs, parent);
e->shape = (cpShape *)cpPolyShapeInitRaw(cpPolyShapeAlloc(), parent->body, 4, verts, 0.0f); // this cast is done in chipmunk, not sure why it works e->shape = (cpShape *)cpPolyShapeInitRaw(cpPolyShapeAlloc(), parent->body, 4, verts, 0.0); // this cast is done in chipmunk, not sure why it works
cpShapeSetUserData(e->shape, (void *)e); cpShapeSetUserData(e->shape, (void *)e);
cpShapeSetMass(e->shape, mass); cpShapeSetMass(e->shape, mass);
cpSpaceAddShape(gs->space, e->shape); cpSpaceAddShape(gs->space, e->shape);
@ -462,7 +462,7 @@ void create_player(Player *player)
void create_missile(GameState *gs, Entity *e) void create_missile(GameState *gs, Entity *e)
{ {
create_body(gs, e); create_body(gs, e);
create_rectangle_shape(gs, e, e, (V2){0}, V2scale(MISSILE_COLLIDER_SIZE, 0.5f), PLAYER_MASS); create_rectangle_shape(gs, e, e, (V2){0}, V2scale(MISSILE_COLLIDER_SIZE, 0.5), PLAYER_MASS);
e->is_missile = true; e->is_missile = true;
} }
@ -471,7 +471,7 @@ void create_player_entity(GameState *gs, Entity *e)
e->is_player = true; e->is_player = true;
e->no_save_to_disk = true; e->no_save_to_disk = true;
create_body(gs, e); create_body(gs, e);
create_rectangle_shape(gs, e, e, (V2){0}, V2scale(PLAYER_SIZE, 0.5f), PLAYER_MASS); create_rectangle_shape(gs, e, e, (V2){0}, V2scale(PLAYER_SIZE, 0.5), PLAYER_MASS);
cpShapeSetFilter(e->shape, PLAYER_SHAPE_FILTER); cpShapeSetFilter(e->shape, PLAYER_SHAPE_FILTER);
} }
@ -494,9 +494,9 @@ void box_create(GameState *gs, Entity *new_box, Entity *grid, V2 pos)
assert(gs->space != NULL); assert(gs->space != NULL);
assert(grid->is_grid); assert(grid->is_grid);
float halfbox = BOX_SIZE / 2.0f; double halfbox = BOX_SIZE / 2.0;
create_rectangle_shape(gs, new_box, grid, pos, (V2){halfbox, halfbox}, 1.0f); create_rectangle_shape(gs, new_box, grid, pos, (V2){halfbox, halfbox}, 1.0);
cpShapeSetFilter(new_box->shape, cpShapeFilterNew(CP_NO_GROUP, BOXES, CP_ALL_CATEGORIES)); cpShapeSetFilter(new_box->shape, cpShapeFilterNew(CP_NO_GROUP, BOXES, CP_ALL_CATEGORIES));
@ -507,7 +507,7 @@ V2 box_compass_vector(Entity *box)
{ {
assert(box->is_box); assert(box->is_box);
V2 to_return = (V2){.x = 1.0f, .y = 0.0f}; V2 to_return = (V2){.x = 1.0, .y = 0.0};
to_return = V2rotate(to_return, rotangle(box->compass_rotation)); to_return = V2rotate(to_return, rotangle(box->compass_rotation));
return to_return; return to_return;
@ -576,13 +576,13 @@ static void grid_correct_for_holes(GameState *gs, struct Entity *grid)
V2 cur_local_pos = entity_shape_pos(N); V2 cur_local_pos = entity_shape_pos(N);
const V2 dirs[] = { const V2 dirs[] = {
(V2){ (V2){
.x = -1.0f, .y = 0.0f}, .x = -1.0, .y = 0.0},
(V2){ (V2){
.x = 1.0f, .y = 0.0f}, .x = 1.0, .y = 0.0},
(V2){ (V2){
.x = 0.0f, .y = 1.0f}, .x = 0.0, .y = 1.0},
(V2){ (V2){
.x = 0.0f, .y = -1.0f}, .x = 0.0, .y = -1.0},
}; };
int num_dirs = sizeof(dirs) / sizeof(*dirs); int num_dirs = sizeof(dirs) / sizeof(*dirs);
@ -593,7 +593,7 @@ static void grid_correct_for_holes(GameState *gs, struct Entity *grid)
// @Robust @Speed faster method, not O(N^2), of getting the box // @Robust @Speed faster method, not O(N^2), of getting the box
// in the direction currently needed // in the direction currently needed
V2 compass_vect = box_compass_vector(N); V2 compass_vect = box_compass_vector(N);
if (N->box_type == BoxMerge && N->wants_disconnect && V2equal(compass_vect, dir, 0.01f)) if (N->box_type == BoxMerge && N->wants_disconnect && V2equal(compass_vect, dir, 0.01))
{ {
} }
else else
@ -601,7 +601,7 @@ static void grid_correct_for_holes(GameState *gs, struct Entity *grid)
V2 wanted_local_pos = V2add(cur_local_pos, V2scale(dir, BOX_SIZE)); V2 wanted_local_pos = V2add(cur_local_pos, V2scale(dir, BOX_SIZE));
BOXES_ITER(gs, cur, grid) BOXES_ITER(gs, cur, grid)
{ {
if (V2equal(entity_shape_pos(cur), wanted_local_pos, 0.01f)) if (V2equal(entity_shape_pos(cur), wanted_local_pos, 0.01))
{ {
box_in_direction = get_id(gs, cur); box_in_direction = get_id(gs, cur);
break; break;
@ -611,7 +611,7 @@ static void grid_correct_for_holes(GameState *gs, struct Entity *grid)
Entity *newbox = get_entity(gs, box_in_direction); Entity *newbox = get_entity(gs, box_in_direction);
if (newbox != NULL && newbox->box_type == BoxMerge && newbox->wants_disconnect && V2equal(V2scale(box_compass_vector(newbox), -1.0f), dir, 0.01f)) if (newbox != NULL && newbox->box_type == BoxMerge && newbox->wants_disconnect && V2equal(V2scale(box_compass_vector(newbox), -1.0), dir, 0.01))
{ {
newbox = NULL; newbox = NULL;
} }
@ -706,9 +706,9 @@ static void on_damage(cpArbiter *arb, cpSpace *space, cpDataPointer userData)
{ {
cpVect collision_point = getPointFunc(arb, i); cpVect collision_point = getPointFunc(arb, i);
V2 local_collision_point = cp_to_v2(cpBodyWorldToLocal(missile->body, collision_point)); V2 local_collision_point = cp_to_v2(cpBodyWorldToLocal(missile->body, collision_point));
if (local_collision_point.x > MISSILE_COLLIDER_SIZE.x * 0.2f) if (local_collision_point.x > MISSILE_COLLIDER_SIZE.x * 0.2)
{ {
missile->damage += MISSILE_DAMAGE_THRESHOLD * 2.0f; missile->damage += MISSILE_DAMAGE_THRESHOLD * 2.0;
} }
} }
} }
@ -717,14 +717,14 @@ static void on_damage(cpArbiter *arb, cpSpace *space, cpDataPointer userData)
// if(entity_a->is_missile) {getPointFunc = cpArbiterGetPointA; // if(entity_a->is_missile) {getPointFunc = cpArbiterGetPointA;
// if(entity_b->is_missile) getPointFunc = cpArbiterGetPointB; // if(entity_b->is_missile) getPointFunc = cpArbiterGetPointB;
float damage = V2length(cp_to_v2(cpArbiterTotalImpulse(arb))) * COLLISION_DAMAGE_SCALING; double damage = V2length(cp_to_v2(cpArbiterTotalImpulse(arb))) * COLLISION_DAMAGE_SCALING;
if (entity_a->is_box && entity_a->box_type == BoxExplosive) if (entity_a->is_box && entity_a->box_type == BoxExplosive)
entity_a->damage += 2.0f * EXPLOSION_DAMAGE_THRESHOLD; entity_a->damage += 2.0 * EXPLOSION_DAMAGE_THRESHOLD;
if (entity_b->is_box && entity_b->box_type == BoxExplosive) if (entity_b->is_box && entity_b->box_type == BoxExplosive)
entity_b->damage += 2.0f * EXPLOSION_DAMAGE_THRESHOLD; entity_b->damage += 2.0 * EXPLOSION_DAMAGE_THRESHOLD;
if (damage > 0.05f) if (damage > 0.05)
{ {
// Log("Collision with damage %f\n", damage); // Log("Collision with damage %f\n", damage);
entity_a->damage += damage; entity_a->damage += damage;
@ -794,8 +794,8 @@ V2 grid_snapped_box_pos(Entity *grid, V2 world)
V2 local = grid_world_to_local(grid, 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 = round(local.x);
local.y = roundf(local.y); local.y = round(local.y);
local.x *= BOX_SIZE; local.x *= BOX_SIZE;
local.y *= BOX_SIZE; local.y *= BOX_SIZE;
@ -803,7 +803,7 @@ V2 grid_snapped_box_pos(Entity *grid, V2 world)
} }
// for boxes does not include box's compass rotation // for boxes does not include box's compass rotation
float entity_rotation(Entity *e) double entity_rotation(Entity *e)
{ {
assert(e->body != NULL || e->shape != NULL); assert(e->body != NULL || e->shape != NULL);
if (e->body != NULL) if (e->body != NULL)
@ -812,7 +812,7 @@ float entity_rotation(Entity *e)
return (float)cpBodyGetAngle(cpShapeGetBody(e->shape)); return (float)cpBodyGetAngle(cpShapeGetBody(e->shape));
} }
float entity_angular_velocity(Entity *grid) double entity_angular_velocity(Entity *grid)
{ {
return (float)cpBodyGetAngularVelocity(grid->body); return (float)cpBodyGetAngularVelocity(grid->body);
} }
@ -828,12 +828,12 @@ V2 entity_shape_pos(Entity *box)
{ {
return cp_to_v2(cpShapeGetCenterOfGravity(box->shape)); return cp_to_v2(cpShapeGetCenterOfGravity(box->shape));
} }
float entity_shape_mass(Entity *box) double entity_shape_mass(Entity *box)
{ {
assert(box->shape != NULL); assert(box->shape != NULL);
return (float)cpShapeGetMass(box->shape); return (float)cpShapeGetMass(box->shape);
} }
float box_rotation(Entity *box) double box_rotation(Entity *box)
{ {
return (float)cpBodyGetAngle(cpShapeGetBody(box->shape)); return (float)cpBodyGetAngle(cpShapeGetBody(box->shape));
} }
@ -863,8 +863,8 @@ struct BodyData
{ {
V2 pos; V2 pos;
V2 vel; V2 vel;
float rotation; double rotation;
float angular_velocity; double angular_velocity;
}; };
void populate(cpBody *body, struct BodyData *data) void populate(cpBody *body, struct BodyData *data)
@ -1120,7 +1120,7 @@ SerMaybeFailure ser_entity(SerState *ser, GameState *gs, Entity *e)
shape_pos = entity_shape_pos(e); shape_pos = entity_shape_pos(e);
SER_MAYBE_RETURN(ser_V2(ser, &shape_pos)); SER_MAYBE_RETURN(ser_V2(ser, &shape_pos));
float shape_mass; double shape_mass;
if (ser->serializing) if (ser->serializing)
shape_mass = entity_shape_mass(e); shape_mass = entity_shape_mass(e);
SER_VAR(&shape_mass); SER_VAR(&shape_mass);
@ -1642,7 +1642,7 @@ static void cloaking_shield_callback_func(cpShape *shape, cpContactPointSet *poi
// has to be global var because can only get this information // has to be global var because can only get this information
static THREADLOCAL cpShape *closest_to_point_in_radius_result = NULL; static THREADLOCAL cpShape *closest_to_point_in_radius_result = NULL;
static THREADLOCAL float closest_to_point_in_radius_result_largest_dist = 0.0f; static THREADLOCAL double closest_to_point_in_radius_result_largest_dist = 0.0;
static THREADLOCAL bool (*closest_to_point_in_radius_filter_func)(Entity *); static THREADLOCAL bool (*closest_to_point_in_radius_filter_func)(Entity *);
static void closest_point_callback_func(cpShape *shape, cpContactPointSet *points, void *data) static void closest_point_callback_func(cpShape *shape, cpContactPointSet *points, void *data)
{ {
@ -1653,8 +1653,8 @@ static void closest_point_callback_func(cpShape *shape, cpContactPointSet *point
if (closest_to_point_in_radius_filter_func != NULL && !closest_to_point_in_radius_filter_func(e)) if (closest_to_point_in_radius_filter_func != NULL && !closest_to_point_in_radius_filter_func(e))
return; return;
float dist = V2length(cp_to_v2(cpvsub(points->points[0].pointA, points->points[0].pointB))); double dist = V2length(cp_to_v2(cpvsub(points->points[0].pointA, points->points[0].pointB)));
// float dist = -points->points[0].distance; // double 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;
@ -1664,12 +1664,12 @@ static void closest_point_callback_func(cpShape *shape, cpContactPointSet *point
// filter func null means everything is ok, if it's not null and returns false, that means // filter func null means everything is ok, if it's not null and returns false, that means
// exclude it from the selection. This returns the closest box entity! // exclude it from the selection. This returns the closest box entity!
Entity *closest_box_to_point_in_radius(struct GameState *gs, V2 point, float radius, bool (*filter_func)(Entity *)) Entity *closest_box_to_point_in_radius(struct GameState *gs, V2 point, double radius, bool (*filter_func)(Entity *))
{ {
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.0;
closest_to_point_in_radius_filter_func = filter_func; closest_to_point_in_radius_filter_func = filter_func;
cpBody *tmpbody = cpBodyNew(0.0f, 0.0f); cpBody *tmpbody = cpBodyNew(0.0, 0.0);
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);
@ -1695,9 +1695,9 @@ static bool scanner_filter(Entity *e)
return true; return true;
} }
static float cur_explosion_damage = 0.0f; static double cur_explosion_damage = 0.0;
static V2 explosion_origin = {0}; static V2 explosion_origin = {0};
static float explosion_push_strength = 0.0f; static double explosion_push_strength = 0.0;
static void explosion_callback_func(cpShape *shape, cpContactPointSet *points, void *data) static void explosion_callback_func(cpShape *shape, cpContactPointSet *points, void *data)
{ {
GameState *gs = (GameState *)data; GameState *gs = (GameState *)data;
@ -1709,10 +1709,10 @@ static void explosion_callback_func(cpShape *shape, cpContactPointSet *points, v
cpBodyApplyImpulseAtWorldPoint(parent->body, v2_to_cp(impulse), v2_to_cp(from_pos)); cpBodyApplyImpulseAtWorldPoint(parent->body, v2_to_cp(impulse), v2_to_cp(from_pos));
} }
static void do_explosion(GameState *gs, Entity *explosion, float dt) static void do_explosion(GameState *gs, Entity *explosion, double dt)
{ {
cpBody *tmpbody = cpBodyNew(0.0f, 0.0f); cpBody *tmpbody = cpBodyNew(0.0, 0.0);
cpShape *circle = cpCircleShapeNew(tmpbody, explosion->explosion_radius, v2_to_cp(explosion_origin)); cpShape *circle = cpCircleShapeNew(tmpbody, explosion->explosion_radius, v2_to_cp(explosion_origin));
cur_explosion_damage = dt * EXPLOSION_DAMAGE_PER_SEC; cur_explosion_damage = dt * EXPLOSION_DAMAGE_PER_SEC;
@ -1727,7 +1727,7 @@ static void do_explosion(GameState *gs, Entity *explosion, float dt)
V2 box_facing_vector(Entity *box) V2 box_facing_vector(Entity *box)
{ {
assert(box->is_box); assert(box->is_box);
V2 to_return = (V2){.x = 1.0f, .y = 0.0f}; V2 to_return = (V2){.x = 1.0, .y = 0.0};
to_return = box_compass_vector(box); to_return = box_compass_vector(box);
to_return = V2rotate(to_return, box_rotation(box)); to_return = V2rotate(to_return, box_rotation(box));
@ -1754,11 +1754,11 @@ enum CompassRotation facing_vector_to_compass(Entity *grid_to_transplant_to, Ent
Down}; Down};
int smallest = -1; int smallest = -1;
float smallest_dist = INFINITY; double smallest_dist = INFINITY;
for (int i = 0; i < ARRLEN(dirs); i++) for (int i = 0; i < ARRLEN(dirs); i++)
{ {
V2 point = V2rotate((V2){.x = 1.0f}, rotangle(dirs[i])); V2 point = V2rotate((V2){.x = 1.0}, rotangle(dirs[i]));
float dist = V2dist(point, local_facing); double dist = V2dist(point, local_facing);
if (dist < smallest_dist) if (dist < smallest_dist)
{ {
smallest_dist = dist; smallest_dist = dist;
@ -1799,9 +1799,9 @@ V2 get_world_hand_pos(GameState *gs, InputFrame *input, Entity *player)
return potentially_snap_hand_pos(gs, V2add(entity_pos(player), input->hand_pos)); return potentially_snap_hand_pos(gs, V2add(entity_pos(player), input->hand_pos));
} }
bool batteries_have_capacity_for(GameState *gs, Entity *grid, float *energy_left_over, float energy_to_use) bool batteries_have_capacity_for(GameState *gs, Entity *grid, double *energy_left_over, double energy_to_use)
{ {
float seen_energy = 0.0f; double seen_energy = 0.0;
BOXES_ITER(gs, possible_battery, grid) BOXES_ITER(gs, possible_battery, grid)
{ {
if (possible_battery->box_type == BoxBattery) if (possible_battery->box_type == BoxBattery)
@ -1816,11 +1816,11 @@ bool batteries_have_capacity_for(GameState *gs, Entity *grid, float *energy_left
} }
// returns any energy unable to burn // returns any energy unable to burn
float batteries_use_energy(GameState *gs, Entity *grid, float *energy_left_over, float energy_to_use) double batteries_use_energy(GameState *gs, Entity *grid, double *energy_left_over, double energy_to_use)
{ {
if (*energy_left_over > 0.0f) if (*energy_left_over > 0.0)
{ {
float energy_to_use_from_leftover = fminf(*energy_left_over, energy_to_use); double energy_to_use_from_leftover = fmin(*energy_left_over, energy_to_use);
*energy_left_over -= energy_to_use_from_leftover; *energy_left_over -= energy_to_use_from_leftover;
energy_to_use -= energy_to_use_from_leftover; energy_to_use -= energy_to_use_from_leftover;
} }
@ -1829,26 +1829,26 @@ float batteries_use_energy(GameState *gs, Entity *grid, float *energy_left_over,
if (possible_battery->box_type == BoxBattery) if (possible_battery->box_type == BoxBattery)
{ {
Entity *battery = possible_battery; Entity *battery = possible_battery;
float energy_to_burn_from_this_battery = fminf(BATTERY_CAPACITY - battery->energy_used, energy_to_use); double energy_to_burn_from_this_battery = fmin(BATTERY_CAPACITY - battery->energy_used, energy_to_use);
battery->energy_used += energy_to_burn_from_this_battery; battery->energy_used += energy_to_burn_from_this_battery;
energy_to_use -= energy_to_burn_from_this_battery; energy_to_use -= energy_to_burn_from_this_battery;
if (energy_to_use <= 0.0f) if (energy_to_use <= 0.0)
return 0.0f; return 0.0;
} }
} }
return energy_to_use; return energy_to_use;
} }
float sun_dist_no_gravity(Entity *sun) double sun_dist_no_gravity(Entity *sun)
{ {
// return (GRAVITY_CONSTANT * (SUN_MASS * mass / (distance * distance))) / mass; // return (GRAVITY_CONSTANT * (SUN_MASS * mass / (distance * distance))) / mass;
// 0.01f = (GRAVITY_CONSTANT * (SUN_MASS / (distance_sqr))); // 0.01 = (GRAVITY_CONSTANT * (SUN_MASS / (distance_sqr)));
// 0.01f / GRAVITY_CONSTANT = SUN_MASS / distance_sqr; // 0.01 / GRAVITY_CONSTANT = SUN_MASS / distance_sqr;
// distance = sqrt( SUN_MASS / (0.01f / GRAVITY_CONSTANT) ) // distance = sqrt( SUN_MASS / (0.01 / GRAVITY_CONSTANT) )
return sqrtf(sun->sun_mass / (GRAVITY_SMALLEST / GRAVITY_CONSTANT)); return sqrt(sun->sun_mass / (GRAVITY_SMALLEST / GRAVITY_CONSTANT));
} }
float entity_mass(Entity *m) double entity_mass(Entity *m)
{ {
if (m->body != NULL) if (m->body != NULL)
return (float)cpBodyGetMass(m->body); return (float)cpBodyGetMass(m->body);
@ -1859,7 +1859,7 @@ float entity_mass(Entity *m)
else else
{ {
assert(false); assert(false);
return 0.0f; return 0.0;
} }
} }
@ -1872,21 +1872,21 @@ V2 sun_gravity_accel_for_entity(Entity *entity_with_gravity, Entity *sun)
if (V2length(V2sub(entity_pos(entity_with_gravity), entity_pos(sun))) > sun_dist_no_gravity(sun)) if (V2length(V2sub(entity_pos(entity_with_gravity), entity_pos(sun))) > sun_dist_no_gravity(sun))
return (V2){0}; return (V2){0};
V2 rel_vector = V2sub(entity_pos(entity_with_gravity), entity_pos(sun)); V2 rel_vector = V2sub(entity_pos(entity_with_gravity), entity_pos(sun));
float mass = entity_mass(entity_with_gravity); double mass = entity_mass(entity_with_gravity);
assert(mass != 0.0f); assert(mass != 0.0);
float distance_sqr = V2lengthsqr(rel_vector); double distance_sqr = V2lengthsqr(rel_vector);
// return (GRAVITY_CONSTANT * (SUN_MASS * mass / (distance * distance))) / mass; // return (GRAVITY_CONSTANT * (SUN_MASS * mass / (distance * distance))) / mass;
// the mass divides out // the mass divides out
// on top // on top
float accel_magnitude = (GRAVITY_CONSTANT * (sun->sun_mass / (distance_sqr))); double accel_magnitude = (GRAVITY_CONSTANT * (sun->sun_mass / (distance_sqr)));
if (distance_sqr <= sun->sun_radius) if (distance_sqr <= sun->sun_radius)
{ {
accel_magnitude *= -1.0f; accel_magnitude *= -1.0;
if (distance_sqr <= sun->sun_radius * 0.25f) if (distance_sqr <= sun->sun_radius * 0.25)
accel_magnitude = 0.0f; accel_magnitude = 0.0;
} }
V2 towards_sun = V2normalize(V2scale(rel_vector, -1.0f)); V2 towards_sun = V2normalize(V2scale(rel_vector, -1.0));
return V2scale(towards_sun, accel_magnitude); return V2scale(towards_sun, accel_magnitude);
#endif // NO_GRAVITY #endif // NO_GRAVITY
} }
@ -1907,11 +1907,11 @@ void entity_ensure_in_orbit(GameState *gs, Entity *e)
SUNS_ITER(gs) SUNS_ITER(gs)
{ {
V2 gravity_accel = sun_gravity_accel_for_entity(e, i.sun); V2 gravity_accel = sun_gravity_accel_for_entity(e, i.sun);
if (V2length(gravity_accel) > 0.0f) if (V2length(gravity_accel) > 0.0)
{ {
float dist = V2length(V2sub(entity_pos(e), entity_pos(i.sun))); double dist = V2length(V2sub(entity_pos(e), entity_pos(i.sun)));
V2 orthogonal_to_gravity = V2normalize(V2rotate(gravity_accel, PI / 2.0f)); V2 orthogonal_to_gravity = V2normalize(V2rotate(gravity_accel, PI / 2.0));
V2 wanted_vel = V2scale(orthogonal_to_gravity, sqrtf(V2length(gravity_accel) * dist)); V2 wanted_vel = V2scale(orthogonal_to_gravity, sqrt(V2length(gravity_accel) * dist));
total_new_vel = cpvadd(total_new_vel, v2_to_cp(wanted_vel)); total_new_vel = cpvadd(total_new_vel, v2_to_cp(wanted_vel));
} }
@ -1960,11 +1960,11 @@ void create_bomb_station(GameState *gs, V2 pos, enum BoxType platonic_type)
BOX_AT_TYPE(grid, ((V2){BOX_SIZE * 4, 0}), BoxHullpiece); BOX_AT_TYPE(grid, ((V2){BOX_SIZE * 4, 0}), BoxHullpiece);
indestructible = true; indestructible = true;
for (float y = -BOX_SIZE * 5.0; y <= BOX_SIZE * 5.0; y += BOX_SIZE) for (double y = -BOX_SIZE * 5.0; y <= BOX_SIZE * 5.0; y += BOX_SIZE)
{ {
BOX_AT_TYPE(grid, ((V2){BOX_SIZE * 5.0, y}), BoxHullpiece); BOX_AT_TYPE(grid, ((V2){BOX_SIZE * 5.0, y}), BoxHullpiece);
} }
for (float x = -BOX_SIZE * 5.0; x <= BOX_SIZE * 5.0; x += BOX_SIZE) for (double x = -BOX_SIZE * 5.0; x <= BOX_SIZE * 5.0; x += BOX_SIZE)
{ {
BOX_AT_TYPE(grid, ((V2){x, BOX_SIZE * 5.0}), BoxHullpiece); BOX_AT_TYPE(grid, ((V2){x, BOX_SIZE * 5.0}), BoxHullpiece);
BOX_AT_TYPE(grid, ((V2){x, -BOX_SIZE * 5.0}), BoxHullpiece); BOX_AT_TYPE(grid, ((V2){x, -BOX_SIZE * 5.0}), BoxHullpiece);
@ -1998,12 +1998,12 @@ void create_hard_shell_station(GameState *gs, V2 pos, enum BoxType platonic_type
BOX_AT_TYPE(grid, ((V2){BOX_SIZE * 4, 0}), BoxHullpiece); BOX_AT_TYPE(grid, ((V2){BOX_SIZE * 4, 0}), BoxHullpiece);
indestructible = true; indestructible = true;
for (float y = -BOX_SIZE * 5.0; y <= BOX_SIZE * 5.0; y += BOX_SIZE) for (double y = -BOX_SIZE * 5.0; y <= BOX_SIZE * 5.0; y += BOX_SIZE)
{ {
BOX_AT_TYPE(grid, ((V2){BOX_SIZE * 5.0, y}), BoxHullpiece); BOX_AT_TYPE(grid, ((V2){BOX_SIZE * 5.0, y}), BoxHullpiece);
BOX_AT_TYPE(grid, ((V2){-BOX_SIZE * 5.0, y}), BoxHullpiece); BOX_AT_TYPE(grid, ((V2){-BOX_SIZE * 5.0, y}), BoxHullpiece);
} }
for (float x = -BOX_SIZE * 5.0; x <= BOX_SIZE * 5.0; x += BOX_SIZE) for (double x = -BOX_SIZE * 5.0; x <= BOX_SIZE * 5.0; x += BOX_SIZE)
{ {
BOX_AT_TYPE(grid, ((V2){x, BOX_SIZE * 5.0}), BoxHullpiece); BOX_AT_TYPE(grid, ((V2){x, BOX_SIZE * 5.0}), BoxHullpiece);
BOX_AT_TYPE(grid, ((V2){x, -BOX_SIZE * 5.0}), BoxHullpiece); BOX_AT_TYPE(grid, ((V2){x, -BOX_SIZE * 5.0}), BoxHullpiece);
@ -2014,11 +2014,11 @@ void create_hard_shell_station(GameState *gs, V2 pos, enum BoxType platonic_type
void create_initial_world(GameState *gs) void create_initial_world(GameState *gs)
{ {
EntityID suns[] = { EntityID suns[] = {
create_sun(gs, new_entity(gs), ((V2){100.0f, 0.0f}), ((V2){0.0f, 0.0f}), 100000.0f, 20.0f), create_sun(gs, new_entity(gs), ((V2){100.0, 0.0}), ((V2){0.0, 0.0}), 100000.0, 20.0),
create_sun(gs, new_entity(gs), ((V2){100.0f, 50.0f}), ((V2){10.0f, 0.0f}), 10000.0f, 10.0f), create_sun(gs, new_entity(gs), ((V2){100.0, 50.0}), ((V2){10.0, 0.0}), 10000.0, 10.0),
create_sun(gs, new_entity(gs), ((V2){100.0f, -50.0f}), ((V2){-10.0f, 0.0f}), 10000.0f, 10.0f), create_sun(gs, new_entity(gs), ((V2){100.0, -50.0}), ((V2){-10.0, 0.0}), 10000.0, 10.0),
create_sun(gs, new_entity(gs), ((V2){50.0f, 200.0f}), ((V2){5.0f, 0.0f}), 400000.0f, 30.0f), create_sun(gs, new_entity(gs), ((V2){50.0, 200.0}), ((V2){5.0, 0.0}), 400000.0, 30.0),
create_sun(gs, new_entity(gs), ((V2){-200.0f, 200.0f}), ((V2){-15.0f, 0.0f}), 900000.0f, 60.0f), create_sun(gs, new_entity(gs), ((V2){-200.0, 200.0}), ((V2){-15.0, 0.0}), 900000.0, 60.0),
}; };
for (int i = 0; i < ARRLEN(suns); i++) for (int i = 0; i < ARRLEN(suns); i++)
@ -2029,27 +2029,27 @@ void create_initial_world(GameState *gs)
#ifdef DEBUG_WORLD #ifdef DEBUG_WORLD
Log("Creating debug world\n"); Log("Creating debug world\n");
// pos, mass, radius // pos, mass, radius
create_bomb_station(gs, (V2){-5.0f, 0.0f}, BoxExplosive); create_bomb_station(gs, (V2){-5.0, 0.0}, BoxExplosive);
create_bomb_station(gs, (V2){0.0f, 5.0f}, BoxGyroscope); create_bomb_station(gs, (V2){0.0, 5.0}, BoxGyroscope);
create_hard_shell_station(gs, (V2){-5.0f, 5.0f}, BoxCloaking); create_hard_shell_station(gs, (V2){-5.0, 5.0}, BoxCloaking);
bool indestructible = false; bool indestructible = false;
float theta = deg2rad(65.0f); double theta = deg2rad(65.0);
V2 from = (V2){BOX_SIZE * 4.0f, -1}; V2 from = (V2){BOX_SIZE * 4.0, -1};
enum CompassRotation rot = Right; enum CompassRotation rot = Right;
{ {
Entity *grid = new_entity(gs); Entity *grid = new_entity(gs);
grid_create(gs, grid); grid_create(gs, grid);
entity_set_pos(grid, V2add(from, V2rotate((V2){.x = -BOX_SIZE * 9.0f}, theta))); entity_set_pos(grid, V2add(from, V2rotate((V2){.x = -BOX_SIZE * 9.0}, theta)));
cpBodySetAngle(grid->body, theta + PI); cpBodySetAngle(grid->body, theta + PI);
rot = Left; rot = Left;
BOX_AT_TYPE(grid, ((V2){0.0f, 0.0f}), BoxMerge); BOX_AT_TYPE(grid, ((V2){0.0, 0.0}), BoxMerge);
BOX_AT(grid, ((V2){0.0f, -BOX_SIZE})); BOX_AT(grid, ((V2){0.0, -BOX_SIZE}));
BOX_AT_TYPE(grid, ((V2){BOX_SIZE, 0.0f}), BoxMerge); BOX_AT_TYPE(grid, ((V2){BOX_SIZE, 0.0}), BoxMerge);
entity_ensure_in_orbit(gs, grid); entity_ensure_in_orbit(gs, grid);
} }
@ -2059,21 +2059,21 @@ void create_initial_world(GameState *gs)
entity_set_pos(grid, from); entity_set_pos(grid, from);
cpBodySetAngle(grid->body, theta); cpBodySetAngle(grid->body, theta);
rot = Left; rot = Left;
BOX_AT_TYPE(grid, ((V2){-BOX_SIZE, 0.0f}), BoxMerge); BOX_AT_TYPE(grid, ((V2){-BOX_SIZE, 0.0}), BoxMerge);
rot = Down; rot = Down;
BOX_AT_TYPE(grid, ((V2){0.0f, 0.0f}), BoxMerge); BOX_AT_TYPE(grid, ((V2){0.0, 0.0}), BoxMerge);
rot = Up; rot = Up;
BOX_AT_TYPE(grid, ((V2){0.0f, BOX_SIZE}), BoxMerge); BOX_AT_TYPE(grid, ((V2){0.0, BOX_SIZE}), BoxMerge);
cpBodySetVelocity(grid->body, v2_to_cp(V2rotate((V2){-0.4f, 0.0f}, theta))); cpBodySetVelocity(grid->body, v2_to_cp(V2rotate((V2){-0.4, 0.0}, theta)));
entity_ensure_in_orbit(gs, grid); entity_ensure_in_orbit(gs, grid);
} }
#else #else
create_bomb_station(gs, (V2){-200.0f, 0.0f}, BoxExplosive); create_bomb_station(gs, (V2){-200.0, 0.0}, BoxExplosive);
create_hard_shell_station(gs, (V2){0.0f, 400.0f}, BoxGyroscope); create_hard_shell_station(gs, (V2){0.0, 400.0}, BoxGyroscope);
create_bomb_station(gs, (V2){0.0f, -150.0f}, BoxCloaking); create_bomb_station(gs, (V2){0.0, -150.0}, BoxCloaking);
create_bomb_station(gs, (V2){300.0f, 300.0f}, BoxMissileLauncher); create_bomb_station(gs, (V2){300.0, 300.0}, BoxMissileLauncher);
create_hard_shell_station(gs, (V2){50.0f, 100.0f}, BoxMerge); create_hard_shell_station(gs, (V2){50.0, 100.0}, BoxMerge);
#endif #endif
} }
@ -2090,7 +2090,7 @@ void process_fixed_timestep(GameState *gs)
process(gs, TIMESTEP); process(gs, TIMESTEP);
} }
void process(GameState *gs, float dt) void process(GameState *gs, double dt)
{ {
assert(gs->space != NULL); assert(gs->space != NULL);
@ -2115,7 +2115,7 @@ void process(GameState *gs, float dt)
if (V2length(from_sun->sun_pos) >= INSTANT_DEATH_DISTANCE_FROM_CENTER) if (V2length(from_sun->sun_pos) >= INSTANT_DEATH_DISTANCE_FROM_CENTER)
{ {
from_sun->sun_vel = V2scale(from_sun->sun_vel, -0.8f); from_sun->sun_vel = V2scale(from_sun->sun_vel, -0.8);
from_sun->sun_pos = V2scale(V2normalize(from_sun->sun_pos), INSTANT_DEATH_DISTANCE_FROM_CENTER); from_sun->sun_pos = V2scale(V2normalize(from_sun->sun_pos), INSTANT_DEATH_DISTANCE_FROM_CENTER);
} }
#endif #endif
@ -2167,7 +2167,7 @@ void process(GameState *gs, float dt)
if (medbay != NULL) if (medbay != NULL)
{ {
exit_seat(gs, medbay, p); exit_seat(gs, medbay, p);
p->damage = 0.95f; p->damage = 0.95;
} }
} }
assert(p->is_player); assert(p->is_player);
@ -2189,14 +2189,14 @@ void process(GameState *gs, float dt)
} }
#ifdef INFINITE_RESOURCES #ifdef INFINITE_RESOURCES
p->damage = 0.0f; p->damage = 0.0;
#endif #endif
// update gold win condition // update gold win condition
if (V2length(V2sub(cp_to_v2(cpBodyGetPosition(p->body)), gs->goldpos)) < GOLD_COLLECT_RADIUS) if (V2length(V2sub(cp_to_v2(cpBodyGetPosition(p->body)), gs->goldpos)) < GOLD_COLLECT_RADIUS)
{ {
p->goldness += 0.1f; p->goldness += 0.1;
p->damage = 0.0f; p->damage = 0.0;
gs->goldpos = (V2){.x = hash11((float)gs->time) * 20.0f, .y = hash11((float)gs->time - 13.6f) * 20.0f}; gs->goldpos = (V2){.x = hash11((float)gs->time) * 20.0, .y = hash11((float)gs->time - 13.6) * 20.0};
} }
#if 1 #if 1
V2 world_hand_pos = get_world_hand_pos(gs, &player->input, p); V2 world_hand_pos = get_world_hand_pos(gs, &player->input, p);
@ -2207,7 +2207,7 @@ void process(GameState *gs, float dt)
if (seat_maybe_in == NULL) // not in any seat if (seat_maybe_in == NULL) // not in any seat
{ {
cpPointQueryInfo query_info = {0}; cpPointQueryInfo query_info = {0};
cpShape *result = cpSpacePointQueryNearest(gs->space, v2_to_cp(world_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.1, 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);
@ -2255,20 +2255,20 @@ void process(GameState *gs, float dt)
{ {
// no cheating by making movement bigger than length 1 // no cheating by making movement bigger than length 1
V2 movement_this_tick = (V2){0}; V2 movement_this_tick = (V2){0};
float rotation_this_tick = 0.0f; double rotation_this_tick = 0.0;
if (V2length(player->input.movement) > 0.0f) if (V2length(player->input.movement) > 0.0)
{ {
movement_this_tick = V2scale(V2normalize(player->input.movement), clamp(V2length(player->input.movement), 0.0f, 1.0f)); movement_this_tick = V2scale(V2normalize(player->input.movement), clamp(V2length(player->input.movement), 0.0, 1.0));
player->input.movement = (V2){0}; player->input.movement = (V2){0};
} }
if (fabsf(player->input.rotation) > 0.0f) if (fabs(player->input.rotation) > 0.0)
{ {
rotation_this_tick = player->input.rotation; rotation_this_tick = player->input.rotation;
if (rotation_this_tick > 1.0f) if (rotation_this_tick > 1.0)
rotation_this_tick = 1.0f; rotation_this_tick = 1.0;
if (rotation_this_tick < -1.0f) if (rotation_this_tick < -1.0)
rotation_this_tick = -1.0f; rotation_this_tick = -1.0;
player->input.rotation = 0.0f; player->input.rotation = 0.0;
} }
Entity *seat_inside_of = get_entity(gs, p->currently_inside_of_box); Entity *seat_inside_of = get_entity(gs, p->currently_inside_of_box);
@ -2287,7 +2287,7 @@ void process(GameState *gs, float dt)
cpBodyApplyForceAtWorldPoint(p->body, v2_to_cp(V2scale(movement_this_tick, PLAYER_JETPACK_FORCE)), cpBodyGetPosition(p->body)); cpBodyApplyForceAtWorldPoint(p->body, v2_to_cp(V2scale(movement_this_tick, PLAYER_JETPACK_FORCE)), cpBodyGetPosition(p->body));
cpBodySetTorque(p->body, rotation_this_tick * PLAYER_JETPACK_TORQUE); cpBodySetTorque(p->body, rotation_this_tick * PLAYER_JETPACK_TORQUE);
p->damage += V2length(movement_this_tick) * dt * PLAYER_JETPACK_SPICE_PER_SECOND; p->damage += V2length(movement_this_tick) * dt * PLAYER_JETPACK_SPICE_PER_SECOND;
p->damage += fabsf(rotation_this_tick) * dt * PLAYER_JETPACK_ROTATION_ENERGY_PER_SECOND; p->damage += fabs(rotation_this_tick) * dt * PLAYER_JETPACK_ROTATION_ENERGY_PER_SECOND;
} }
else else
{ {
@ -2306,7 +2306,7 @@ void process(GameState *gs, float dt)
Entity *g = get_entity(gs, seat_inside_of->shape_parent_entity); Entity *g = get_entity(gs, seat_inside_of->shape_parent_entity);
V2 target_direction = {0}; V2 target_direction = {0};
if (V2length(movement_this_tick) > 0.0f) if (V2length(movement_this_tick) > 0.0)
{ {
target_direction = V2normalize(movement_this_tick); target_direction = V2normalize(movement_this_tick);
} }
@ -2315,7 +2315,7 @@ void process(GameState *gs, float dt)
if (cur->box_type == BoxThruster) if (cur->box_type == BoxThruster)
{ {
float wanted_thrust = -V2dot(target_direction, box_facing_vector(cur)); double wanted_thrust = -V2dot(target_direction, box_facing_vector(cur));
wanted_thrust = clamp01(wanted_thrust); wanted_thrust = clamp01(wanted_thrust);
cur->wanted_thrust = wanted_thrust; cur->wanted_thrust = wanted_thrust;
} }
@ -2338,7 +2338,7 @@ void process(GameState *gs, float dt)
// @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 = grid_to_build_on(gs, world_hand_pos); Entity *target_grid = grid_to_build_on(gs, world_hand_pos);
cpShape *maybe_box_to_destroy = cpSpacePointQueryNearest(gs->space, v2_to_cp(world_build), 0.01f, cpShapeFilterNew(CP_NO_GROUP, CP_ALL_CATEGORIES, BOXES), &info); cpShape *maybe_box_to_destroy = cpSpacePointQueryNearest(gs->space, v2_to_cp(world_build), 0.01, cpShapeFilterNew(CP_NO_GROUP, CP_ALL_CATEGORIES, BOXES), &info);
if (maybe_box_to_destroy != NULL) if (maybe_box_to_destroy != NULL)
{ {
Entity *cur_box = cp_shape_entity(maybe_box_to_destroy); Entity *cur_box = cp_shape_entity(maybe_box_to_destroy);
@ -2354,7 +2354,7 @@ void process(GameState *gs, float dt)
// creating a box // creating a box
p->damage += DAMAGE_TO_PLAYER_PER_BLOCK; p->damage += DAMAGE_TO_PLAYER_PER_BLOCK;
V2 created_box_position; V2 created_box_position;
if (p->damage < 1.0f) // player can't create a box that kills them by making it if (p->damage < 1.0) // player can't create a box that kills them by making it
{ {
if (target_grid == NULL) if (target_grid == NULL)
{ {
@ -2383,7 +2383,7 @@ void process(GameState *gs, float dt)
} }
} }
#endif #endif
if (p->damage >= 1.0f) if (p->damage >= 1.0)
{ {
entity_destroy(gs, p); entity_destroy(gs, p);
player->entity = (EntityID){0}; player->entity = (EntityID){0};
@ -2442,7 +2442,7 @@ void process(GameState *gs, float dt)
sqdist = cpvlengthsq(cpvsub(v2_to_cp(entity_pos(e)), v2_to_cp(entity_pos(i.sun)))); sqdist = cpvlengthsq(cpvsub(v2_to_cp(entity_pos(e)), v2_to_cp(entity_pos(i.sun))));
if (sqdist < (i.sun->sun_radius * i.sun->sun_radius)) if (sqdist < (i.sun->sun_radius * i.sun->sun_radius))
{ {
e->damage += 10.0f * dt; e->damage += 10.0 * dt;
} }
} }
@ -2472,7 +2472,7 @@ void process(GameState *gs, float dt)
if (is_burning(e)) if (is_burning(e))
{ {
e->time_burned_for += dt; e->time_burned_for += dt;
cpBodyApplyForceAtWorldPoint(e->body, v2_to_cp(V2rotate((V2){.x = MISSILE_BURN_FORCE, .y = 0.0f}, entity_rotation(e))), v2_to_cp(entity_pos(e))); cpBodyApplyForceAtWorldPoint(e->body, v2_to_cp(V2rotate((V2){.x = MISSILE_BURN_FORCE, .y = 0.0}, entity_rotation(e))), v2_to_cp(entity_pos(e)));
} }
if (e->damage >= MISSILE_DAMAGE_THRESHOLD && e->time_burned_for >= MISSILE_ARM_TIME) if (e->damage >= MISSILE_DAMAGE_THRESHOLD && e->time_burned_for >= MISSILE_ARM_TIME)
{ {
@ -2490,7 +2490,7 @@ void process(GameState *gs, float dt)
{ {
if (e->is_platonic) if (e->is_platonic)
{ {
e->damage = 0.0f; e->damage = 0.0;
gs->platonic_positions[(int)e->box_type] = entity_pos(e); gs->platonic_positions[(int)e->box_type] = entity_pos(e);
} }
if (e->box_type == BoxExplosive && e->damage >= EXPLOSION_DAMAGE_THRESHOLD) if (e->box_type == BoxExplosive && e->damage >= EXPLOSION_DAMAGE_THRESHOLD)
@ -2523,21 +2523,21 @@ void process(GameState *gs, float dt)
Entity *other_grid = box_grid(other_merge); Entity *other_grid = box_grid(other_merge);
// the merges are near eachother, but are they facing eachother... // the merges are near eachother, but are they facing eachother...
bool from_facing_other = V2dot(box_facing_vector(from_merge), V2normalize(V2sub(entity_pos(other_merge), entity_pos(from_merge)))) > 0.8f; bool from_facing_other = V2dot(box_facing_vector(from_merge), V2normalize(V2sub(entity_pos(other_merge), entity_pos(from_merge)))) > 0.8;
bool other_facing_from = V2dot(box_facing_vector(other_merge), V2normalize(V2sub(entity_pos(from_merge), entity_pos(other_merge)))) > 0.8f; bool other_facing_from = V2dot(box_facing_vector(other_merge), V2normalize(V2sub(entity_pos(from_merge), entity_pos(other_merge)))) > 0.8;
// using this stuff to detect if when the other grid's boxes are snapped, they'll be snapped // using this stuff to detect if when the other grid's boxes are snapped, they'll be snapped
// to be next to the from merge box // to be next to the from merge box
V2 actual_new_pos = grid_snapped_box_pos(from_grid, entity_pos(other_merge)); V2 actual_new_pos = grid_snapped_box_pos(from_grid, entity_pos(other_merge));
V2 needed_new_pos = V2add(entity_pos(from_merge), V2scale(box_facing_vector(from_merge), BOX_SIZE)); V2 needed_new_pos = V2add(entity_pos(from_merge), V2scale(box_facing_vector(from_merge), BOX_SIZE));
if (from_facing_other && other_facing_from && V2equal(needed_new_pos, actual_new_pos, 0.01f)) if (from_facing_other && other_facing_from && V2equal(needed_new_pos, actual_new_pos, 0.01))
{ {
// do the merge // do the merge
V2 facing_vector_needed = V2scale(box_facing_vector(from_merge), -1.0f); V2 facing_vector_needed = V2scale(box_facing_vector(from_merge), -1.0);
V2 current_facing_vector = box_facing_vector(other_merge); V2 current_facing_vector = box_facing_vector(other_merge);
float angle_diff = V2anglediff(current_facing_vector, facing_vector_needed); double angle_diff = V2anglediff(current_facing_vector, facing_vector_needed);
if (angle_diff == FLT_MIN) if (angle_diff == FLT_MIN)
angle_diff = 0.0f; angle_diff = 0.0;
assert(!isnan(angle_diff)); assert(!isnan(angle_diff));
cpBodySetAngle(other_grid->body, cpBodyGetAngle(other_grid->body) + angle_diff); cpBodySetAngle(other_grid->body, cpBodyGetAngle(other_grid->body) + angle_diff);
@ -2566,7 +2566,7 @@ void process(GameState *gs, float dt)
} }
} }
} }
if (e->damage >= 1.0f) if (e->damage >= 1.0)
{ {
grid_remove_box(gs, get_entity(gs, e->shape_parent_entity), e); grid_remove_box(gs, get_entity(gs, e->shape_parent_entity), e);
} }
@ -2575,18 +2575,18 @@ void process(GameState *gs, float dt)
{ {
Entity *grid = e; Entity *grid = e;
// calculate how much energy solar panels provide // calculate how much energy solar panels provide
float energy_to_add = 0.0f; double energy_to_add = 0.0;
BOXES_ITER(gs, cur_box, grid) BOXES_ITER(gs, cur_box, grid)
{ {
if (cur_box->box_type == BoxSolarPanel) if (cur_box->box_type == BoxSolarPanel)
{ {
cur_box->sun_amount = 0.0f; cur_box->sun_amount = 0.0;
SUNS_ITER(gs) SUNS_ITER(gs)
{ {
float new_sun = clamp01(fabsf(V2dot(box_facing_vector(cur_box), V2normalize(V2sub(entity_pos(i.sun), entity_pos(cur_box)))))); double new_sun = clamp01(fabs(V2dot(box_facing_vector(cur_box), V2normalize(V2sub(entity_pos(i.sun), entity_pos(cur_box))))));
// less sun the farther away you are! // less sun the farther away you are!
new_sun *= lerp(1.0f, 0.0f, clamp01(V2length(V2sub(entity_pos(cur_box), entity_pos(i.sun))) / sun_dist_no_gravity(i.sun))); new_sun *= lerp(1.0, 0.0, clamp01(V2length(V2sub(entity_pos(cur_box), entity_pos(i.sun))) / sun_dist_no_gravity(i.sun)));
cur_box->sun_amount += new_sun; cur_box->sun_amount += new_sun;
} }
energy_to_add += cur_box->sun_amount * SOLAR_ENERGY_PER_SECOND * dt; energy_to_add += cur_box->sun_amount * SOLAR_ENERGY_PER_SECOND * dt;
@ -2596,19 +2596,19 @@ void process(GameState *gs, float dt)
// apply all of the energy to all connected batteries // apply all of the energy to all connected batteries
BOXES_ITER(gs, cur, grid) BOXES_ITER(gs, cur, grid)
{ {
if (energy_to_add <= 0.0f) if (energy_to_add <= 0.0)
break; break;
if (cur->box_type == BoxBattery) if (cur->box_type == BoxBattery)
{ {
float energy_sucked_up_by_battery = cur->energy_used < energy_to_add ? cur->energy_used : energy_to_add; double energy_sucked_up_by_battery = cur->energy_used < energy_to_add ? cur->energy_used : energy_to_add;
cur->energy_used -= energy_sucked_up_by_battery; cur->energy_used -= energy_sucked_up_by_battery;
energy_to_add -= energy_sucked_up_by_battery; energy_to_add -= energy_sucked_up_by_battery;
} }
assert(energy_to_add >= 0.0f); assert(energy_to_add >= 0.0);
} }
// any energy_to_add existing now can also be used to power thrusters/medbay // any energy_to_add existing now can also be used to power thrusters/medbay
float non_battery_energy_left_over = energy_to_add; double non_battery_energy_left_over = energy_to_add;
// use the energy, stored in the batteries, in various boxes // use the energy, stored in the batteries, in various boxes
BOXES_ITER(gs, cur_box, grid) BOXES_ITER(gs, cur_box, grid)
@ -2616,25 +2616,25 @@ void process(GameState *gs, float dt)
if (cur_box->box_type == BoxThruster) if (cur_box->box_type == BoxThruster)
{ {
float energy_to_consume = cur_box->wanted_thrust * THRUSTER_ENERGY_USED_PER_SECOND * dt; double energy_to_consume = cur_box->wanted_thrust * THRUSTER_ENERGY_USED_PER_SECOND * dt;
if (energy_to_consume > 0.0f) if (energy_to_consume > 0.0)
{ {
cur_box->thrust = 0.0f; cur_box->thrust = 0.0;
float energy_unconsumed = batteries_use_energy(gs, grid, &non_battery_energy_left_over, energy_to_consume); double energy_unconsumed = batteries_use_energy(gs, grid, &non_battery_energy_left_over, energy_to_consume);
cur_box->thrust = (1.0f - energy_unconsumed / energy_to_consume) * cur_box->wanted_thrust; cur_box->thrust = (1.0 - energy_unconsumed / energy_to_consume) * cur_box->wanted_thrust;
if (cur_box->thrust >= 0.0f) if (cur_box->thrust >= 0.0)
cpBodyApplyForceAtWorldPoint(grid->body, v2_to_cp(thruster_force(cur_box)), v2_to_cp(entity_pos(cur_box))); cpBodyApplyForceAtWorldPoint(grid->body, v2_to_cp(thruster_force(cur_box)), v2_to_cp(entity_pos(cur_box)));
} }
} }
if (cur_box->box_type == BoxGyroscope) if (cur_box->box_type == BoxGyroscope)
{ {
float energy_to_consume = fabsf(cur_box->wanted_thrust * GYROSCOPE_ENERGY_USED_PER_SECOND * dt); double energy_to_consume = fabs(cur_box->wanted_thrust * GYROSCOPE_ENERGY_USED_PER_SECOND * dt);
if (energy_to_consume > 0.0f) if (energy_to_consume > 0.0)
{ {
cur_box->thrust = 0.0f; cur_box->thrust = 0.0;
float energy_unconsumed = batteries_use_energy(gs, grid, &non_battery_energy_left_over, energy_to_consume); double energy_unconsumed = batteries_use_energy(gs, grid, &non_battery_energy_left_over, energy_to_consume);
cur_box->thrust = (1.0f - energy_unconsumed / energy_to_consume) * cur_box->wanted_thrust; cur_box->thrust = (1.0 - energy_unconsumed / energy_to_consume) * cur_box->wanted_thrust;
if (fabsf(cur_box->thrust) >= 0.0f) if (fabs(cur_box->thrust) >= 0.0)
cpBodySetTorque(grid->body, cpBodyGetTorque(grid->body) + cur_box->thrust * GYROSCOPE_TORQUE); cpBodySetTorque(grid->body, cpBodyGetTorque(grid->body) + cur_box->thrust * GYROSCOPE_TORQUE);
} }
} }
@ -2643,30 +2643,30 @@ void process(GameState *gs, float dt)
Entity *potential_meatbag_to_heal = get_entity(gs, cur_box->player_who_is_inside_of_me); Entity *potential_meatbag_to_heal = get_entity(gs, cur_box->player_who_is_inside_of_me);
if (potential_meatbag_to_heal != NULL) if (potential_meatbag_to_heal != NULL)
{ {
float wanted_energy_use = fminf(potential_meatbag_to_heal->damage, PLAYER_ENERGY_RECHARGE_PER_SECOND * dt); double wanted_energy_use = fmin(potential_meatbag_to_heal->damage, PLAYER_ENERGY_RECHARGE_PER_SECOND * dt);
if (wanted_energy_use > 0.0f) if (wanted_energy_use > 0.0)
{ {
float energy_unconsumed = batteries_use_energy(gs, grid, &non_battery_energy_left_over, wanted_energy_use); double energy_unconsumed = batteries_use_energy(gs, grid, &non_battery_energy_left_over, wanted_energy_use);
potential_meatbag_to_heal->damage -= (1.0f - energy_unconsumed / wanted_energy_use) * wanted_energy_use; potential_meatbag_to_heal->damage -= (1.0 - energy_unconsumed / wanted_energy_use) * wanted_energy_use;
} }
} }
} }
if (cur_box->box_type == BoxCloaking) if (cur_box->box_type == BoxCloaking)
{ {
float energy_unconsumed = batteries_use_energy(gs, grid, &non_battery_energy_left_over, CLOAKING_ENERGY_USE * dt); double energy_unconsumed = batteries_use_energy(gs, grid, &non_battery_energy_left_over, CLOAKING_ENERGY_USE * dt);
if (energy_unconsumed >= CLOAKING_ENERGY_USE * dt) if (energy_unconsumed >= CLOAKING_ENERGY_USE * dt)
{ {
cur_box->cloaking_power = lerp(cur_box->cloaking_power, 0.0, dt * 3.0f); cur_box->cloaking_power = lerp(cur_box->cloaking_power, 0.0, dt * 3.0);
} }
else else
{ {
cur_box->cloaking_power = lerp(cur_box->cloaking_power, 1.0, dt * 3.0f); cur_box->cloaking_power = lerp(cur_box->cloaking_power, 1.0, dt * 3.0);
cpBody *tmp = cpBodyNew(0.0, 0.0); cpBody *tmp = cpBodyNew(0.0, 0.0);
cpBodySetPosition(tmp, v2_to_cp(entity_pos(cur_box))); cpBodySetPosition(tmp, v2_to_cp(entity_pos(cur_box)));
cpBodySetAngle(tmp, entity_rotation(cur_box)); cpBodySetAngle(tmp, entity_rotation(cur_box));
// subtract a little from the panel size so that boxes just at the boundary of the panel // subtract a little from the panel size so that boxes just at the boundary of the panel
// aren't (sometimes cloaked)/(sometimes not) from floating point imprecision // aren't (sometimes cloaked)/(sometimes not) from floating point imprecision
cpShape *box_shape = cpBoxShapeNew(tmp, CLOAKING_PANEL_SIZE - 0.03f, CLOAKING_PANEL_SIZE - 0.03f, 0.0); cpShape *box_shape = cpBoxShapeNew(tmp, CLOAKING_PANEL_SIZE - 0.03, CLOAKING_PANEL_SIZE - 0.03, 0.0);
cpSpaceShapeQuery(gs->space, box_shape, cloaking_shield_callback_func, (void *)cur_box); cpSpaceShapeQuery(gs->space, box_shape, cloaking_shield_callback_func, (void *)cur_box);
cpShapeFree(box_shape); cpShapeFree(box_shape);
cpBodyFree(tmp); cpBodyFree(tmp);
@ -2676,21 +2676,21 @@ void process(GameState *gs, float dt)
{ {
LauncherTarget target = missile_launcher_target(gs, cur_box); LauncherTarget target = missile_launcher_target(gs, cur_box);
if (cur_box->missile_construction_charge < 1.0f) if (cur_box->missile_construction_charge < 1.0)
{ {
float want_use_energy = dt * MISSILE_CHARGE_RATE; double want_use_energy = dt * MISSILE_CHARGE_RATE;
float energy_charged = want_use_energy - batteries_use_energy(gs, grid, &non_battery_energy_left_over, want_use_energy); double energy_charged = want_use_energy - batteries_use_energy(gs, grid, &non_battery_energy_left_over, want_use_energy);
cur_box->missile_construction_charge += energy_charged; cur_box->missile_construction_charge += energy_charged;
} }
if (target.target_found && cur_box->missile_construction_charge >= 1.0f) if (target.target_found && cur_box->missile_construction_charge >= 1.0)
{ {
cur_box->missile_construction_charge = 0.0f; cur_box->missile_construction_charge = 0.0;
Entity *new_missile = new_entity(gs); Entity *new_missile = new_entity(gs);
create_missile(gs, new_missile); create_missile(gs, new_missile);
new_missile->owning_squad = cur_box->owning_squad; // missiles have teams and attack eachother! new_missile->owning_squad = cur_box->owning_squad; // missiles have teams and attack eachother!
float missile_spawn_dist = sqrtf((BOX_SIZE / 2.0f) * (BOX_SIZE / 2.0f) * 2.0f) + MISSILE_COLLIDER_SIZE.x / 2.0f + 0.1f; double missile_spawn_dist = sqrt((BOX_SIZE / 2.0) * (BOX_SIZE / 2.0) * 2.0) + MISSILE_COLLIDER_SIZE.x / 2.0 + 0.1;
cpBodySetPosition(new_missile->body, v2_to_cp(V2add(entity_pos(cur_box), V2rotate((V2){.x = missile_spawn_dist, 0.0f}, target.facing_angle)))); cpBodySetPosition(new_missile->body, v2_to_cp(V2add(entity_pos(cur_box), V2rotate((V2){.x = missile_spawn_dist, 0.0}, target.facing_angle))));
cpBodySetAngle(new_missile->body, target.facing_angle); cpBodySetAngle(new_missile->body, target.facing_angle);
cpBodySetVelocity(new_missile->body, v2_to_cp(box_vel(cur_box))); cpBodySetVelocity(new_missile->body, v2_to_cp(box_vel(cur_box)));
} }
@ -2700,23 +2700,23 @@ void process(GameState *gs, float dt)
// set the nearest platonic solid! only on server as only the server sees everything // set the nearest platonic solid! only on server as only the server sees everything
if (gs->server_side_computing) if (gs->server_side_computing)
{ {
float energy_unconsumed = batteries_use_energy(gs, grid, &non_battery_energy_left_over, SCANNER_ENERGY_USE * dt); double energy_unconsumed = batteries_use_energy(gs, grid, &non_battery_energy_left_over, SCANNER_ENERGY_USE * dt);
if (energy_unconsumed >= SCANNER_ENERGY_USE * dt) if (energy_unconsumed >= SCANNER_ENERGY_USE * dt)
{ {
cur_box->platonic_detection_strength = 0.0f; cur_box->platonic_detection_strength = 0.0;
cur_box->platonic_nearest_direction = (V2){0}; cur_box->platonic_nearest_direction = (V2){0};
} }
else else
{ {
V2 from_pos = entity_pos(cur_box); V2 from_pos = entity_pos(cur_box);
V2 nearest = {0}; V2 nearest = {0};
float nearest_dist = INFINITY; double nearest_dist = INFINITY;
for (int i = 0; i < MAX_BOX_TYPES; i++) for (int i = 0; i < MAX_BOX_TYPES; i++)
{ {
V2 cur_pos = gs->platonic_positions[i]; V2 cur_pos = gs->platonic_positions[i];
if (V2length(cur_pos) > 0.0f) // zero is uninitialized, the platonic solid doesn't exist (probably) @Robust do better if (V2length(cur_pos) > 0.0) // zero is uninitialized, the platonic solid doesn't exist (probably) @Robust do better
{ {
float length_to_cur = V2dist(from_pos, cur_pos); double length_to_cur = V2dist(from_pos, cur_pos);
if (length_to_cur < nearest_dist) if (length_to_cur < nearest_dist)
{ {
nearest_dist = length_to_cur; nearest_dist = length_to_cur;
@ -2727,12 +2727,12 @@ void process(GameState *gs, float dt)
if (nearest_dist < INFINITY) if (nearest_dist < INFINITY)
{ {
cur_box->platonic_nearest_direction = V2normalize(V2sub(nearest, from_pos)); cur_box->platonic_nearest_direction = V2normalize(V2sub(nearest, from_pos));
cur_box->platonic_detection_strength = fmaxf(0.1f, 1.0f - fminf(1.0f, nearest_dist / 100.0f)); cur_box->platonic_detection_strength = fmax(0.1, 1.0 - fmin(1.0, nearest_dist / 100.0));
} }
else else
{ {
cur_box->platonic_nearest_direction = (V2){0}; cur_box->platonic_nearest_direction = (V2){0};
cur_box->platonic_detection_strength = 0.0f; cur_box->platonic_detection_strength = 0.0;
} }
} }
} }
@ -2747,27 +2747,27 @@ void process(GameState *gs, float dt)
if (!entityids_same(cur_box->currently_scanning, new_id)) if (!entityids_same(cur_box->currently_scanning, new_id))
{ {
cur_box->currently_scanning_progress = 0.0f; cur_box->currently_scanning_progress = 0.0;
cur_box->currently_scanning = new_id; cur_box->currently_scanning = new_id;
} }
float target_head_rotate_speed = cur_box->platonic_detection_strength > 0.0f ? 3.0f : 0.0f; double target_head_rotate_speed = cur_box->platonic_detection_strength > 0.0 ? 3.0 : 0.0;
if (to_learn != NULL) if (to_learn != NULL)
{ {
cur_box->currently_scanning_progress += dt * SCANNER_SCAN_RATE; cur_box->currently_scanning_progress += dt * SCANNER_SCAN_RATE;
target_head_rotate_speed *= 30.0f * cur_box->currently_scanning_progress; target_head_rotate_speed *= 30.0 * cur_box->currently_scanning_progress;
} }
else else
cur_box->currently_scanning_progress = 0.0f; cur_box->currently_scanning_progress = 0.0;
if (cur_box->currently_scanning_progress >= 1.0f) if (cur_box->currently_scanning_progress >= 1.0)
{ {
cur_box->blueprints_learned |= box_unlock_number(to_learn->box_type); cur_box->blueprints_learned |= box_unlock_number(to_learn->box_type);
} }
cur_box->scanner_head_rotate_speed = lerp(cur_box->scanner_head_rotate_speed, target_head_rotate_speed, dt * 3.0f); cur_box->scanner_head_rotate_speed = lerp(cur_box->scanner_head_rotate_speed, target_head_rotate_speed, dt * 3.0);
cur_box->scanner_head_rotate += cur_box->scanner_head_rotate_speed * dt; cur_box->scanner_head_rotate += cur_box->scanner_head_rotate_speed * dt;
cur_box->scanner_head_rotate = fmodf(cur_box->scanner_head_rotate, 2.0f * PI); cur_box->scanner_head_rotate = fmod(cur_box->scanner_head_rotate, 2.0 * PI);
} }
} }
} }

658
main.c

File diff suppressed because it is too large Load Diff

@ -141,7 +141,7 @@ void server(void *info_raw)
{ {
Entity *grid = new_entity(&gs); Entity *grid = new_entity(&gs);
grid_create(&gs, grid); grid_create(&gs, grid);
entity_set_pos(grid, (V2){-BOX_SIZE * 2, 0.0f}); entity_set_pos(grid, (V2){-BOX_SIZE * 2, 0.0});
Entity *box = new_entity(&gs); Entity *box = new_entity(&gs);
box_create(&gs, box, grid, (V2){0}); box_create(&gs, box, grid, (V2){0});
} }
@ -151,10 +151,10 @@ void server(void *info_raw)
{ {
Entity *grid = new_entity(&gs); Entity *grid = new_entity(&gs);
grid_create(&gs, grid); grid_create(&gs, grid);
entity_set_pos(grid, (V2){-BOX_SIZE * 2, 0.0f}); entity_set_pos(grid, (V2){-BOX_SIZE * 2, 0.0});
entity_set_rotation(grid, PI / 1.7f); entity_set_rotation(grid, PI / 1.7);
cpBodySetVelocity(grid->body, cpv(-0.1, 0.0)); cpBodySetVelocity(grid->body, cpv(-0.1, 0.0));
cpBodySetAngularVelocity(grid->body, 1.0f); cpBodySetAngularVelocity(grid->body, 1.0);
BOX_AT(grid, ((V2){0})); BOX_AT(grid, ((V2){0}));
BOX_AT(grid, ((V2){BOX_SIZE, 0})); BOX_AT(grid, ((V2){BOX_SIZE, 0}));
@ -196,8 +196,8 @@ void server(void *info_raw)
uint64_t last_saved_world_time = stm_now(); uint64_t last_saved_world_time = stm_now();
uint64_t last_sent_audio_time = stm_now(); uint64_t last_sent_audio_time = stm_now();
uint64_t last_sent_gamestate_time = stm_now(); uint64_t last_sent_gamestate_time = stm_now();
float audio_time_to_send = 0.0f; double audio_time_to_send = 0.0;
float total_time = 0.0f; double total_time = 0.0;
unsigned char *world_save_buffer = malloc(entities_size); unsigned char *world_save_buffer = malloc(entities_size);
while (true) while (true)
{ {
@ -337,7 +337,7 @@ void server(void *info_raw)
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...
const float max_time = 5.0f * TIMESTEP; const double max_time = 5.0 * TIMESTEP;
if (total_time > max_time) if (total_time > max_time)
{ {
Log("Abnormally large total time %f, clamping\n", total_time); Log("Abnormally large total time %f, clamping\n", total_time);
@ -414,7 +414,7 @@ void server(void *info_raw)
audio_time_to_send += (float)stm_sec(stm_diff(stm_now(), last_sent_audio_time)); audio_time_to_send += (float)stm_sec(stm_diff(stm_now(), last_sent_audio_time));
last_sent_audio_time = stm_now(); last_sent_audio_time = stm_now();
int num_audio_packets = (int)floor(1.0f / (VOIP_TIME_PER_PACKET / audio_time_to_send)); int num_audio_packets = (int)floor(1.0 / (VOIP_TIME_PER_PACKET / audio_time_to_send));
#define MAX_AUDIO_PACKETS_TO_SEND 12 #define MAX_AUDIO_PACKETS_TO_SEND 12
if (num_audio_packets > MAX_AUDIO_PACKETS_TO_SEND) if (num_audio_packets > MAX_AUDIO_PACKETS_TO_SEND)
@ -467,9 +467,9 @@ void server(void *info_raw)
Entity *other_player_entity = get_entity(&gs, gs.players[other_player_index].entity); Entity *other_player_entity = get_entity(&gs, gs.players[other_player_index].entity);
if (other_player_entity != NULL) if (other_player_entity != NULL)
{ {
float dist = V2dist(entity_pos(this_player_entity), entity_pos(other_player_entity)); double dist = V2dist(entity_pos(this_player_entity), entity_pos(other_player_entity));
float volume = lerp(1.0f, 0.0f, clamp01(dist / VOIP_DISTANCE_WHEN_CANT_HEAR)); double volume = lerp(1.0, 0.0, clamp01(dist / VOIP_DISTANCE_WHEN_CANT_HEAR));
if (volume > 0.01f) if (volume > 0.01)
{ {
for (int frame_i = 0; frame_i < VOIP_EXPECTED_FRAME_COUNT; frame_i++) for (int frame_i = 0; frame_i < VOIP_EXPECTED_FRAME_COUNT; frame_i++)
{ {

@ -20,7 +20,7 @@ void term(int signum)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct sigaction action; struct sigaction action;
memset(&action, 0, sizeof(struct sigaction)); memset(&action, 0, sizeo(struct sigaction));
action.sa_handler = term; action.sa_handler = term;
sigaction(SIGTERM, &action, NULL); sigaction(SIGTERM, &action, NULL);

@ -112,25 +112,15 @@
#endif #endif
// including headers from headers bad // including headers from headers bad
#ifndef SOKOL_GP_INCLUDED
void sgp_set_color(float, float, float, float);
// @Robust use double precision for all vectors, when passed back to sokol
// somehow automatically or easily cast to floats
typedef struct sgp_vec2
{
float x, y;
} sgp_vec2;
typedef sgp_vec2 sgp_point;
#endif
#ifndef CHIPMUNK_H #ifndef CHIPMUNK_H
typedef void cpSpace; typedef void cpSpace;
typedef void cpBody; typedef void cpBody;
typedef void cpShape; typedef void cpShape;
typedef struct cpVect
{
double x, y;
} cpVect;
#endif #endif
#include "queue.h" #include "queue.h"
@ -148,8 +138,7 @@ typedef int opus_int32;
#endif #endif
typedef sgp_vec2 V2; typedef cpVect V2;
typedef sgp_point P2;
#define Log(...) \ #define Log(...) \
{ \ { \
@ -212,7 +201,7 @@ typedef struct InputFrame
{ {
uint64_t tick; uint64_t tick;
V2 movement; V2 movement;
float rotation; double rotation;
int take_over_squad; // -1 means not taking over any squad int take_over_squad; // -1 means not taking over any squad
bool accept_cur_squad_invite; bool accept_cur_squad_invite;
@ -236,7 +225,7 @@ typedef struct Entity
bool no_save_to_disk; // stuff generated later on, like player's bodies or space stations that respawn. bool no_save_to_disk; // stuff generated later on, like player's bodies or space stations that respawn.
float damage; // used by box and player double damage; // used by box and player
cpBody *body; // used by grid, player, and box cpBody *body; // used by grid, player, and box
cpShape *shape; // must be a box so shape_size can be set appropriately, and serialized cpShape *shape; // must be a box so shape_size can be set appropriately, and serialized
@ -256,30 +245,30 @@ typedef struct Entity
enum Squad owning_squad; // also controls what the player can see, because of cloaking! enum Squad owning_squad; // also controls what the player can see, because of cloaking!
EntityID currently_inside_of_box; EntityID currently_inside_of_box;
enum Squad squad_invited_to; // if squad none, then no squad invite enum Squad squad_invited_to; // if squad none, then no squad invite
float goldness; // how much the player is a winner double goldness; // how much the player is a winner
// explosion // explosion
bool is_explosion; bool is_explosion;
V2 explosion_pos; V2 explosion_pos;
V2 explosion_vel; V2 explosion_vel;
float explosion_progress; // in seconds double explosion_progress; // in seconds
float explosion_push_strength; double explosion_push_strength;
float explosion_radius; double explosion_radius;
// sun // sun
bool is_sun; bool is_sun;
V2 sun_vel; V2 sun_vel;
V2 sun_pos; V2 sun_pos;
float sun_mass; double sun_mass;
float sun_radius; double sun_radius;
// missile // missile
bool is_missile; bool is_missile;
float time_burned_for; // until MISSILE_BURN_TIME. Before MISSILE_ARM_TIME cannot explode double time_burned_for; // until MISSILE_BURN_TIME. Before MISSILE_ARM_TIME cannot explode
// grids // grids
bool is_grid; bool is_grid;
float total_energy_capacity; double total_energy_capacity;
EntityID boxes; EntityID boxes;
// boxes // boxes
@ -296,33 +285,33 @@ typedef struct Entity
bool wants_disconnect; // don't serialized, termporary value not used across frames bool wants_disconnect; // don't serialized, termporary value not used across frames
// missile launcher // missile launcher
float missile_construction_charge; double missile_construction_charge;
// used by medbay and cockpit // used by medbay and cockpit
EntityID player_who_is_inside_of_me; EntityID player_who_is_inside_of_me;
// only serialized when box_type is thruster or gyroscope, used for both. Thrust // only serialized when box_type is thruster or gyroscope, used for both. Thrust
// can mean rotation thrust! // can mean rotation thrust!
float wanted_thrust; // the thrust command applied to the thruster double wanted_thrust; // the thrust command applied to the thruster
float thrust; // the actual thrust it can provide based on energy sources in the grid double thrust; // the actual thrust it can provide based on energy sources in the grid
// only serialized when box_type is battery // only serialized when box_type is battery
float energy_used; // battery, between 0 battery capacity. You have to look through code to figure out what that is! haha sucker! double energy_used; // battery, between 0 battery capacity. You have to look through code to figure out what that is! haha sucker!
// only serialized when box_type is solar panel // only serialized when box_type is solar panel
float sun_amount; // solar panel, between 0 and 1 double sun_amount; // solar panel, between 0 and 1
// cloaking only // cloaking only
float cloaking_power; // 0.0 if unable to be used because no power, 1.0 if fully cloaking! double cloaking_power; // 0.0 if unable to be used because no power, 1.0 if fully cloaking!
// scanner only stuff! // scanner only stuff!
EntityID currently_scanning; EntityID currently_scanning;
float currently_scanning_progress; // when 1.0, scans it! double currently_scanning_progress; // when 1.0, scans it!
BOX_UNLOCKS_TYPE blueprints_learned; // @Robust make this same type as blueprints BOX_UNLOCKS_TYPE blueprints_learned; // @Robust make this same type as blueprints
float scanner_head_rotate_speed; // not serialized, cosmetic double scanner_head_rotate_speed; // not serialized, cosmetic
float scanner_head_rotate; double scanner_head_rotate;
V2 platonic_nearest_direction; // normalized V2 platonic_nearest_direction; // normalized
float platonic_detection_strength; // from zero to one double platonic_detection_strength; // from zero to one
} Entity; } Entity;
typedef struct Player typedef struct Player
@ -350,8 +339,8 @@ typedef struct GameState
{ {
cpSpace *space; cpSpace *space;
// @Robust for the integer tick, also store a float for how much time has been processed. // @Robust for the integer tick, also store a double for how much time has been processed.
// Like a whole timestep then a float for subtimestep // Like a whole timestep then a double for subtimestep
double time; // @Robust separate tick integer not prone to precision issues. Could be very large as is saved to disk! double time; // @Robust separate tick integer not prone to precision issues. Could be very large as is saved to disk!
V2 goldpos; V2 goldpos;
@ -381,7 +370,7 @@ typedef struct GameState
#define TAU (PI * 2.0f) #define TAU (PI * 2.0f)
// returns in radians // returns in radians
static float rotangle(enum CompassRotation rot) static double rotangle(enum CompassRotation rot)
{ {
switch (rot) switch (rot)
{ {
@ -436,10 +425,10 @@ void create_initial_world(GameState *gs);
void initialize(struct GameState *gs, void *entity_arena, size_t entity_arena_size); void initialize(struct GameState *gs, void *entity_arena, size_t entity_arena_size);
void destroy(struct GameState *gs); void destroy(struct GameState *gs);
void process_fixed_timestep(GameState *gs); void process_fixed_timestep(GameState *gs);
void process(struct GameState *gs, float dt); // does in place void process(struct GameState *gs, double dt); // does in place
Entity *closest_box_to_point_in_radius(struct GameState *gs, V2 point, float radius, bool (*filter_func)(Entity *)); Entity *closest_box_to_point_in_radius(struct GameState *gs, V2 point, double radius, bool (*filter_func)(Entity *));
uint64_t tick(struct GameState *gs); uint64_t tick(struct GameState *gs);
float sun_dist_no_gravity(Entity *sun); double sun_dist_no_gravity(Entity *sun);
// all of these return if successful or not // all of these return if successful or not
bool server_to_client_serialize(struct ServerToClient *msg, unsigned char *bytes, size_t *out_len, size_t max_len, Entity *for_this_player, bool to_disk); bool server_to_client_serialize(struct ServerToClient *msg, unsigned char *bytes, size_t *out_len, size_t max_len, Entity *for_this_player, bool to_disk);
@ -453,9 +442,9 @@ 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_rotation(Entity *e, double rot);
void entity_set_pos(Entity *e, V2 pos); void entity_set_pos(Entity *e, V2 pos);
float entity_rotation(Entity *e); double entity_rotation(Entity *e);
void entity_ensure_in_orbit(GameState *gs, Entity *e); void entity_ensure_in_orbit(GameState *gs, Entity *e);
void entity_destroy(GameState *gs, Entity *e); void entity_destroy(GameState *gs, 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))
@ -463,7 +452,7 @@ void entity_destroy(GameState *gs, Entity *e);
typedef struct LauncherTarget typedef struct LauncherTarget
{ {
bool target_found; bool target_found;
float facing_angle; // in global coords double facing_angle; // in global coords
} LauncherTarget; } LauncherTarget;
LauncherTarget missile_launcher_target(GameState *gs, Entity *launcher); LauncherTarget missile_launcher_target(GameState *gs, Entity *launcher);
@ -477,9 +466,9 @@ V2 box_vel(Entity *box);
V2 grid_local_to_world(Entity *grid, V2 local); V2 grid_local_to_world(Entity *grid, V2 local);
V2 grid_world_to_local(Entity *grid, V2 world); V2 grid_world_to_local(Entity *grid, V2 world);
V2 grid_snapped_box_pos(Entity *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 entity_angular_velocity(Entity *grid); double entity_angular_velocity(Entity *grid);
V2 entity_shape_pos(Entity *box); V2 entity_shape_pos(Entity *box);
float box_rotation(Entity *box); double box_rotation(Entity *box);
// thruster // thruster
V2 box_facing_vector(Entity *box); V2 box_facing_vector(Entity *box);
@ -500,7 +489,7 @@ typedef struct ServerThreadInfo
typedef struct AABB typedef struct AABB
{ {
float x, y, width, height; double x, y, width, height;
} AABB; } AABB;
static AABB centered_at(V2 point, V2 size) static AABB centered_at(V2 point, V2 size)
@ -526,7 +515,7 @@ static V2 V2add(V2 a, V2 b)
}; };
} }
static V2 V2scale(V2 a, float f) static V2 V2scale(V2 a, double f)
{ {
return (V2){ return (V2){
.x = a.x * f, .x = a.x * f,
@ -534,14 +523,14 @@ static V2 V2scale(V2 a, float f)
}; };
} }
static float V2lengthsqr(V2 v) static double V2lengthsqr(V2 v)
{ {
return v.x * v.x + v.y * v.y; return v.x * v.x + v.y * v.y;
} }
static float V2length(V2 v) static double V2length(V2 v)
{ {
return sqrtf(V2lengthsqr(v)); return sqrt(V2lengthsqr(v));
} }
static V2 V2normalize(V2 v) static V2 V2normalize(V2 v)
@ -549,14 +538,14 @@ static V2 V2normalize(V2 v)
return V2scale(v, 1.0f / V2length(v)); return V2scale(v, 1.0f / V2length(v));
} }
static float V2dot(V2 a, V2 b) static double V2dot(V2 a, V2 b)
{ {
return a.x * b.x + a.y * b.y; return a.x * b.x + a.y * b.y;
} }
static float V2projectvalue(V2 vec, V2 onto) static double V2projectvalue(V2 vec, V2 onto)
{ {
float length_onto = V2length(onto); double length_onto = V2length(onto);
return V2dot(vec, onto) / (length_onto * length_onto); return V2dot(vec, onto) / (length_onto * length_onto);
} }
@ -565,18 +554,18 @@ static V2 V2project(V2 vec, V2 onto)
return V2scale(onto, V2projectvalue(vec, onto)); return V2scale(onto, V2projectvalue(vec, onto));
} }
static V2 V2rotate(V2 vec, float theta) static V2 V2rotate(V2 vec, double theta)
{ {
return (V2){ return (V2){
.x = vec.x * cosf(theta) - vec.y * sinf(theta), .x = vec.x * cos(theta) - vec.y * sin(theta),
.y = vec.x * sinf(theta) + vec.y * cosf(theta), .y = vec.x * sin(theta) + vec.y * cos(theta),
}; };
} }
// also known as atan2 // also known as atan2
static float V2angle(V2 vec) static double V2angle(V2 vec)
{ {
return atan2f(vec.y, vec.x); return atan2(vec.y, vec.x);
} }
static V2 V2sub(V2 a, V2 b) static V2 V2sub(V2 a, V2 b)
@ -587,7 +576,7 @@ static V2 V2sub(V2 a, V2 b)
}; };
} }
static float sign(float f) static double sign(double f)
{ {
if (f >= 0.0f) if (f >= 0.0f)
return 1.0f; return 1.0f;
@ -595,27 +584,27 @@ static float sign(float f)
return -1.0f; return -1.0f;
} }
static bool V2equal(V2 a, V2 b, float eps) static bool V2equal(V2 a, V2 b, double eps)
{ {
return V2length(V2sub(a, b)) < eps; return V2length(V2sub(a, b)) < eps;
} }
static inline float clamp01(float f) static inline double clamp01(double f)
{ {
return fmaxf(0.0f, fminf(f, 1.0f)); return fmax(0.0f, fmin(f, 1.0f));
} }
static float V2distsqr(V2 from, V2 to) static double V2distsqr(V2 from, V2 to)
{ {
return V2lengthsqr(V2sub(to, from)); return V2lengthsqr(V2sub(to, from));
} }
static float V2dist(V2 from, V2 to) static double V2dist(V2 from, V2 to)
{ {
return sqrtf(V2distsqr(from, to)); return sqrt(V2distsqr(from, to));
} }
static inline float clamp(float f, float minimum, float maximum) static inline double clamp(double f, double minimum, double maximum)
{ {
if (f < minimum) if (f < minimum)
return minimum; return minimum;
@ -624,34 +613,34 @@ static inline float clamp(float f, float minimum, float maximum)
return f; return f;
} }
static float V2anglediff(V2 a, V2 b) static double V2anglediff(V2 a, V2 b)
{ {
float acos_input = V2dot(a, b) / (V2length(a) * V2length(b)); double acos_input = V2dot(a, b) / (V2length(a) * V2length(b));
acos_input = clamp(acos_input, -1.0f, 1.0f); acos_input = clamp(acos_input, -1.0f, 1.0f);
assert(acos_input >= -1.0f && acos_input <= 1.0f); assert(acos_input >= -1.0f && acos_input <= 1.0f);
return acosf(acos_input) * sign(V2dot(a, b)); return acos(acos_input) * sign(V2dot(a, b));
} }
static float fract(float f) static double fract(double f)
{ {
return f - floorf(f); return f - floor(f);
} }
static float lerp(float a, float b, float f) static double lerp(double a, double b, double f)
{ {
return a * (1.0f - f) + (b * f); return a * (1.0f - f) + (b * f);
} }
static float lerp_angle(float p_from, float p_to, float p_weight) static double lerp_angle(double p_from, double p_to, double p_weight)
{ {
float difference = fmodf(p_to - p_from, (float)TAU); double difference = fmod(p_to - p_from, (float)TAU);
float distance = fmodf(2.0f * difference, (float)TAU) - difference; double distance = fmod(2.0f * difference, (float)TAU) - difference;
return p_from + distance * p_weight; return p_from + distance * p_weight;
} }
static V2 V2floor(V2 p) static V2 V2floor(V2 p)
{ {
return (V2){floorf(p.x), floorf(p.y)}; return (V2){floor(p.x), floor(p.y)};
} }
static V2 V2fract(V2 p) static V2 V2fract(V2 p)
@ -659,7 +648,7 @@ static V2 V2fract(V2 p)
return (V2){fract(p.x), fract(p.y)}; return (V2){fract(p.x), fract(p.y)};
} }
/* /*
float noise(V2 p) double noise(V2 p)
{ {
V2 id = V2floor(p); V2 id = V2floor(p);
V2 f = V2fract(p); V2 f = V2fract(p);
@ -673,15 +662,15 @@ float noise(V2 p)
u.y); u.y);
} }
float fbm(V2 p) double fbm(V2 p)
{ {
float f = 0.0; double f = 0.0;
float gat = 0.0; double gat = 0.0;
for (float octave = 0.; octave < 5.; ++octave) for (double octave = 0.; octave < 5.; ++octave)
{ {
float la = pow(2.0, octave); double la = pow(2.0, octave);
float ga = pow(0.5, octave + 1.); double ga = pow(0.5, octave + 1.);
f += ga * noise(la * p); f += ga * noise(la * p);
gat += ga; gat += ga;
} }
@ -692,7 +681,7 @@ float fbm(V2 p)
} }
*/ */
static V2 V2lerp(V2 a, V2 b, float factor) static V2 V2lerp(V2 a, V2 b, double factor)
{ {
V2 to_return = {0}; V2 to_return = {0};
to_return.x = lerp(a.x, b.x, factor); to_return.x = lerp(a.x, b.x, factor);
@ -702,72 +691,14 @@ static V2 V2lerp(V2 a, V2 b, float factor)
} }
// for random generation // for random generation
static float hash11(float p) static double hash11(double p)
{ {
p = fract(p * .1031f); p = fract(p * .1031f);
p *= p + 33.33f; p *= p + 33.33f;
p *= p + p; p *= p + p;
return fract(p); return fract(p);
} }
static double deg2rad(double deg)
typedef struct Color
{
float r, g, b, a;
} Color;
static Color colhex(int r, int g, int b)
{
return (Color){
.r = (float)r / 255.0f,
.g = (float)g / 255.0f,
.b = (float)b / 255.0f,
.a = 1.0f,
};
}
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)
{
Color to_return = {0};
to_return.r = lerp(a.r, b.r, factor);
to_return.g = lerp(a.g, b.g, factor);
to_return.b = lerp(a.b, b.b, factor);
to_return.a = lerp(a.a, b.a, factor);
return to_return;
}
static void set_color(Color c)
{
sgp_set_color(c.r, c.g, c.b, c.a);
}
static float deg2rad(float deg)
{ {
return (deg / 360.0f) * 2.0f * PI; return (deg / 360.0f) * 2.0f * PI;
} }
#define WHITE \
(Color) \
{ \
.r = 1.0f, .g = 1.0f, .b = 1.0f, .a = 1.0f \
}
#define RED \
(Color) \
{ \
.r = 1.0f, .g = 0.0f, .b = 0.0f, .a = 1.0f \
}
#define BLUE \
(Color) \
{ \
.r = 0.0f, .g = 0.0f, .b = 1.0f, .a = 1.0f \
}
#define GOLD colhex(255, 215, 0)

Loading…
Cancel
Save