Rotator block and no gravity radius from sun

main
Cameron Murphy Reikes 2 years ago
parent bc22342d75
commit 0902089108

@ -323,6 +323,7 @@ void create_player(Player *player)
unlock_box(player, BoxMedbay);
unlock_box(player, BoxSolarPanel);
unlock_box(player, BoxScanner);
}
void create_player_entity(GameState *gs, Entity *e)
@ -835,6 +836,7 @@ SerMaybeFailure ser_inputframe(SerState *ser, InputFrame *i)
{
SER_VAR(&i->tick);
SER_MAYBE_RETURN(ser_V2(ser, &i->movement));
SER_VAR(&i->rotation);
SER_VAR(&i->take_over_squad);
SER_ASSERT(i->take_over_squad >= 0 || i->take_over_squad == -1);
SER_ASSERT(i->take_over_squad < SquadLast);
@ -972,6 +974,7 @@ SerMaybeFailure ser_entity(SerState *ser, GameState *gs, Entity *e)
SER_MAYBE_RETURN(ser_entityid(ser, &e->player_who_is_inside_of_me));
break;
case BoxThruster:
case BoxGyroscope:
SER_VAR(&e->thrust);
SER_VAR(&e->wanted_thrust);
break;
@ -1519,11 +1522,20 @@ float batteries_use_energy(GameState *gs, Entity *grid, float *energy_left_over,
return energy_to_use;
}
float sun_gravity_at_point(V2 p)
{
if(V2length(V2sub(p, SUN_POS)) > SUN_NO_MORE_ELECTRICITY_OR_GRAVITY)
return 0.0f;
return SUN_GRAVITY_STRENGTH;
}
void entity_ensure_in_orbit(Entity *e)
{
assert(e->body != NULL);
cpVect pos = v2_to_cp(V2sub(entity_pos(e), SUN_POS));
cpFloat r = cpvlength(pos);
cpFloat v = cpfsqrt(SUN_GRAVITY_STRENGTH / r) / r;
cpFloat v = cpfsqrt(sun_gravity_at_point(cp_to_v2(pos)) / r) / r;
cpBodySetVelocity(e->body, cpvmult(cpvperp(pos), v));
}
@ -1534,8 +1546,9 @@ V2 box_vel(Entity *box)
return cp_to_v2(cpBodyGetVelocityAtWorldPoint(grid->body, v2_to_cp(entity_pos(box))));
}
EntityID create_initial_world(GameState *gs)
void create_station(GameState *gs, V2 pos, enum BoxType platonic_type)
{
#define BOX_AT_TYPE(grid, pos, type) \
{ \
Entity *box = new_entity(gs); \
@ -1548,11 +1561,11 @@ EntityID create_initial_world(GameState *gs)
bool indestructible = false;
Entity *grid = new_entity(gs);
grid_create(gs, grid);
entity_set_pos(grid, (V2){-5.0f, 0.0f});
entity_set_pos(grid, pos);
entity_ensure_in_orbit(grid);
Entity *explosion_box = new_entity(gs);
box_create(gs, explosion_box, grid, (V2){0});
explosion_box->box_type = BoxExplosive;
explosion_box->box_type = platonic_type;
explosion_box->is_platonic = true;
BOX_AT_TYPE(grid, ((V2){BOX_SIZE, 0}), BoxExplosive);
BOX_AT_TYPE(grid, ((V2){BOX_SIZE * 2, 0}), BoxHullpiece);
@ -1576,8 +1589,12 @@ EntityID create_initial_world(GameState *gs)
BOX_AT_TYPE(grid, ((V2){-BOX_SIZE * 6.0, -BOX_SIZE * 2.0}), BoxExplosive);
BOX_AT_TYPE(grid, ((V2){-BOX_SIZE * 6.0, -BOX_SIZE * 3.0}), BoxExplosive);
BOX_AT_TYPE(grid, ((V2){-BOX_SIZE * 6.0, -BOX_SIZE * 5.0}), BoxExplosive);
}
return get_id(gs, grid);
void create_initial_world(GameState *gs)
{
create_station(gs, (V2){-50.0f,0.0f}, BoxExplosive);
create_station(gs, (V2){0.0f, 100.0f}, BoxGyroscope);
}
void exit_seat(GameState *gs, Entity *seat_in, Entity *p)
@ -1691,7 +1708,7 @@ void process(GameState *gs, float dt)
Entity *potential_seat = cp_shape_entity(result);
assert(potential_seat->is_box);
if(potential_seat->box_type == BoxScanner) // learn everything from the scanner
if (potential_seat->box_type == BoxScanner) // learn everything from the scanner
{
player->box_unlocks |= potential_seat->blueprints_learned;
}
@ -1725,18 +1742,39 @@ void process(GameState *gs, float dt)
{
// no cheating by making movement bigger than length 1
V2 movement_this_tick = (V2){0};
float rotation_this_tick = 0.0f;
if (V2length(player->input.movement) > 0.0f)
{
movement_this_tick = V2scale(V2normalize(player->input.movement), clamp(V2length(player->input.movement), 0.0f, 1.0f));
player->input.movement = (V2){0};
}
if (fabsf(player->input.rotation) > 0.0f)
{
rotation_this_tick = player->input.rotation;
if (rotation_this_tick > 1.0f)
rotation_this_tick = 1.0f;
if (rotation_this_tick < -1.0f)
rotation_this_tick = -1.0f;
player->input.rotation = 0.0f;
}
Entity *seat_inside_of = get_entity(gs, p->currently_inside_of_box);
// strange rare bug I saw happen, related to explosives, but no idea how to
// reproduce. @Robust put a breakpoint here, reproduce, and fix it!
if(seat_inside_of != NULL && !seat_inside_of->is_box)
{
Log("Strange thing happened where player was in non box seat!\n");
seat_inside_of = NULL;
p->currently_inside_of_box = (EntityID){0};
}
if (seat_inside_of == NULL)
{
cpShapeSetFilter(p->shape, PLAYER_SHAPE_FILTER);
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);
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;
}
else
{
@ -1757,11 +1795,17 @@ void process(GameState *gs, float dt)
}
BOXES_ITER(gs, cur, g)
{
if (cur->box_type != BoxThruster)
continue;
float wanted_thrust = -V2dot(target_direction, box_facing_vector(cur));
wanted_thrust = clamp01(wanted_thrust);
cur->wanted_thrust = wanted_thrust;
if (cur->box_type == BoxThruster)
{
float wanted_thrust = -V2dot(target_direction, box_facing_vector(cur));
wanted_thrust = clamp01(wanted_thrust);
cur->wanted_thrust = wanted_thrust;
}
if(cur->box_type == BoxGyroscope)
{
cur->wanted_thrust = rotation_this_tick;
}
}
}
}
@ -1844,11 +1888,11 @@ void process(GameState *gs, float dt)
if (sqdist > (INSTANT_DEATH_DISTANCE_FROM_SUN * INSTANT_DEATH_DISTANCE_FROM_SUN))
{
bool platonic_found = false;
if(e->is_grid)
if (e->is_grid)
{
BOXES_ITER(gs, cur_box, e)
{
if(cur_box->is_platonic)
if (cur_box->is_platonic)
{
platonic_found = true;
break;
@ -1859,7 +1903,7 @@ void process(GameState *gs, float dt)
{
cpBody *body = e->body;
cpBodySetVelocity(body, cpvmult(cpBodyGetVelocity(body), -1.0));
cpVect rel_to_sun = cpvsub(cpBodyGetPosition(body), v2_to_cp(SUN_POS));
cpVect rel_to_sun = cpvsub(cpBodyGetPosition(body), v2_to_cp(SUN_POS));
cpBodySetPosition(body, cpvadd(v2_to_cp(SUN_POS), cpvmult(cpvnormalize(rel_to_sun), INSTANT_DEATH_DISTANCE_FROM_SUN)));
}
else
@ -1872,7 +1916,8 @@ void process(GameState *gs, float dt)
{
e->damage += 10.0f * dt;
}
cpVect g = cpvmult(p, -SUN_GRAVITY_STRENGTH / (sqdist * cpfsqrt(sqdist)));
cpVect g = cpvmult(p, -sun_gravity_at_point(entity_pos(e)) / (sqdist * cpfsqrt(sqdist)));
cpBodyUpdateVelocity(e->body, g, 1.0f, dt);
}
@ -1914,12 +1959,15 @@ void process(GameState *gs, float dt)
Entity *grid = e;
// calculate how much energy solar panels provide
float energy_to_add = 0.0f;
BOXES_ITER(gs, cur, grid)
BOXES_ITER(gs, cur_box, grid)
{
if (cur->box_type == BoxSolarPanel)
if (cur_box->box_type == BoxSolarPanel)
{
cur->sun_amount = clamp01(V2dot(box_facing_vector(cur), V2normalize(V2sub(SUN_POS, entity_pos(cur)))));
energy_to_add += cur->sun_amount * SOLAR_ENERGY_PER_SECOND * dt;
cur_box->sun_amount = clamp01(V2dot(box_facing_vector(cur_box), V2normalize(V2sub(SUN_POS, entity_pos(cur_box)))));
// less sun the farther away you are!
cur_box->sun_amount *= lerp(1.0f, 0.0f, clamp01(V2length(V2sub(entity_pos(cur_box), SUN_POS))/SUN_NO_MORE_ELECTRICITY_OR_GRAVITY));
energy_to_add += cur_box->sun_amount * SOLAR_ENERGY_PER_SECOND * dt;
}
}
@ -1945,6 +1993,7 @@ void process(GameState *gs, float dt)
{
if (cur_box->box_type == BoxThruster)
{
float energy_to_consume = cur_box->wanted_thrust * THRUSTER_ENERGY_USED_PER_SECOND * dt;
if (energy_to_consume > 0.0f)
{
@ -1955,6 +2004,18 @@ void process(GameState *gs, float dt)
cpBodyApplyForceAtWorldPoint(grid->body, v2_to_cp(thruster_force(cur_box)), v2_to_cp(entity_pos(cur_box)));
}
}
if(cur_box->box_type == BoxGyroscope)
{
float energy_to_consume = fabsf(cur_box->wanted_thrust * GYROSCOPE_ENERGY_USED_PER_SECOND* dt);
if (energy_to_consume > 0.0f)
{
cur_box->thrust = 0.0f;
float 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;
if (fabsf(cur_box->thrust) >= 0.0f)
cpBodySetTorque(grid->body, cpBodyGetTorque(grid->body) + cur_box->thrust*GYROSCOPE_TORQUE);
}
}
if (cur_box->box_type == BoxMedbay)
{
Entity *potential_meatbag_to_heal = get_entity(gs, cur_box->player_who_is_inside_of_me);
@ -2016,7 +2077,6 @@ void process(GameState *gs, float dt)
if (to_learn != NULL)
assert(to_learn->is_box);
EntityID new_id = get_id(gs, to_learn);
if (!entityids_same(cur_box->currently_scanning, new_id))
@ -2025,12 +2085,13 @@ void process(GameState *gs, float dt)
cur_box->currently_scanning = new_id;
}
float target_head_rotate_speed = cur_box->platonic_detection_strength > 0.0f ? 3.0f : 0.0f;
float target_head_rotate_speed = cur_box->platonic_detection_strength > 0.0f ? 3.0f : 0.0f;
if (to_learn != NULL)
{
cur_box->currently_scanning_progress += dt * SCANNER_SCAN_RATE;
target_head_rotate_speed *= 30.0f*cur_box->currently_scanning_progress;
} else
target_head_rotate_speed *= 30.0f * cur_box->currently_scanning_progress;
}
else
cur_box->currently_scanning_progress = 0.0f;
if (cur_box->currently_scanning_progress >= 1.0f)
@ -2038,7 +2099,7 @@ void process(GameState *gs, float dt)
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.0f);
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);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

@ -111,13 +111,13 @@ static sg_image image_scanner_head;
static sg_image image_itemswitch;
static enum BoxType toolbar[TOOLBAR_SLOTS] = {
BoxHullpiece,
BoxThruster,
BoxBattery,
BoxCockpit,
BoxMedbay,
BoxSolarPanel,
BoxScanner,
BoxHullpiece,
BoxThruster,
BoxBattery,
BoxCockpit,
BoxMedbay,
BoxSolarPanel,
BoxScanner,
};
static int cur_toolbar_slot = 0;
static int cur_editing_rotation = Right;
@ -146,7 +146,6 @@ static struct BoxInfo
enum BoxType type;
const char *image_path;
sg_image image;
bool needs_tobe_unlocked;
} boxes[] = {
// if added to here will show up in toolbar, is placeable
{
@ -176,12 +175,15 @@ static struct BoxInfo
{
.type = BoxExplosive,
.image_path = "loaded/explosive.png",
.needs_tobe_unlocked = true,
},
{
.type = BoxScanner,
.image_path = "loaded/scanner_base.png",
.needs_tobe_unlocked = false,
},
{
.type = BoxGyroscope,
.image_path = "loaded/gyroscope.png",
},
};
#define ENTITIES_ITER(cur) \
@ -732,10 +734,10 @@ static void ui(bool draw, float dt, float width, float height)
},
mouse_pos);
item_scaling[i] = lerp(item_scaling[i], item_being_hovered ? 1.3f : 1.0f, dt*4.0f);
item_scaling[i] = lerp(item_scaling[i], item_being_hovered ? 1.3f : 1.0f, dt * 4.0f);
struct BoxInfo info = boxes[i];
if(item_being_hovered && build_pressed && picking_new_boxtype)
if (item_being_hovered && build_pressed && picking_new_boxtype)
{
toolbar[cur_toolbar_slot] = info.type;
build_pressed = false;
@ -1167,7 +1169,7 @@ static void ui(bool draw, float dt, float width, float height)
if (toolbar[i] != BoxInvalid)
{
struct BoxInfo info = boxinfo(toolbar[i]);
if(can_build(info.type))
if (can_build(info.type))
sgp_set_image(0, info.image);
else
sgp_set_image(0, image_mystery);
@ -1448,6 +1450,7 @@ static void frame(void)
if (V2length(input) > 0.0)
input = V2normalize(input);
cur_input_frame.movement = input;
cur_input_frame.rotation = (float)keydown[SAPP_KEYCODE_E] - (float)keydown[SAPP_KEYCODE_Q];
if (interact_pressed)
cur_input_frame.seat_action = interact_pressed;
@ -1772,7 +1775,8 @@ static void frame(void)
if (b->indestructible)
{
sgp_set_color(0.2f, 0.2f, 0.2f, 1.0f);
} else if(b->is_platonic)
}
else if (b->is_platonic)
{
set_color(GOLD);
}
@ -1854,9 +1858,14 @@ static void frame(void)
draw_texture_centered((V2){0}, SUN_RADIUS * 2.0f);
sgp_reset_image(0);
// can draw at 0,0 because everything relative to sun now!
// sun DEATH RADIUS
set_color(RED);
draw_circle((V2){0}, INSTANT_DEATH_DISTANCE_FROM_SUN);
set_color(BLUE);
draw_circle((V2){0}, SUN_NO_MORE_ELECTRICITY_OR_GRAVITY);
}
sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f);

@ -9,8 +9,12 @@
#define PLAYER_SIZE ((V2){.x = BOX_SIZE, .y = BOX_SIZE})
#define PLAYER_MASS 0.5f
#define PLAYER_JETPACK_FORCE 1.5f
#define PLAYER_JETPACK_TORQUE 0.05f
// #define PLAYER_JETPACK_FORCE 20.0f
#define PLAYER_JETPACK_SPICE_PER_SECOND 0.1f
// distance at which things become geostationary and no more solar power!
#define SUN_NO_MORE_ELECTRICITY_OR_GRAVITY 100.0f
#define PLAYER_JETPACK_ROTATION_ENERGY_PER_SECOND 0.2f
#define PLAYER_JETPACK_SPICE_PER_SECOND 0.2f
#define SCANNER_ENERGY_USE 0.05f
#define MAX_HAND_REACH 1.0f
#define SCANNER_SCAN_RATE 0.5f
@ -21,6 +25,8 @@
#define COLLISION_DAMAGE_SCALING 0.15f
#define THRUSTER_FORCE 12.0f
#define THRUSTER_ENERGY_USED_PER_SECOND 0.005f
#define GYROSCOPE_ENERGY_USED_PER_SECOND 0.005f
#define GYROSCOPE_TORQUE 0.5f
#define VISION_RADIUS 12.0f
#define MAX_SERVER_TO_CLIENT 1024 * 512 // maximum size of serialized gamestate buffer
#define MAX_CLIENT_TO_SERVER 1024 * 10 // maximum size of serialized inputs and mic data
@ -32,7 +38,7 @@
#else
#define SUN_GRAVITY_STRENGTH (9.0e2f)
#endif
#define SOLAR_ENERGY_PER_SECOND 0.04f
#define SOLAR_ENERGY_PER_SECOND 0.09f
#define DAMAGE_TO_PLAYER_PER_BLOCK 0.1f
#define BATTERY_CAPACITY 1.5f
#define PLAYER_ENERGY_RECHARGE_PER_SECOND 0.2f
@ -144,6 +150,7 @@ enum BoxType
BoxSolarPanel,
BoxExplosive,
BoxScanner,
BoxGyroscope,
BoxLast,
};
@ -184,6 +191,7 @@ typedef struct InputFrame
{
uint64_t tick;
V2 movement;
float rotation;
int take_over_squad; // -1 means not taking over any squad
bool accept_cur_squad_invite;
@ -248,7 +256,8 @@ typedef struct Entity
// used by medbay and cockpit
EntityID player_who_is_inside_of_me;
// only serialized when box_type is thruster
// only serialized when box_type is thruster or gyroscope, used for both. Thrust
// can mean rotation thrust!
float wanted_thrust; // the thrust command applied to the thruster
float thrust; // the actual thrust it can provide based on energy sources in the grid
@ -362,7 +371,7 @@ void create_player(Player *player);
bool box_unlocked(Player *player, enum BoxType box);
// gamestate
EntityID create_initial_world(GameState *gs);
void create_initial_world(GameState *gs);
void initialize(struct GameState *gs, void *entity_arena, size_t entity_arena_size);
void destroy(struct GameState *gs);
void process_fixed_timestep(GameState *gs);
@ -660,4 +669,6 @@ static void set_color(Color c)
(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