Add solar panel

main
Cameron Murphy Reikes 2 years ago
parent 16f3dfa443
commit ca2e4196d9

@ -235,7 +235,7 @@ void entity_set_rotation(Entity* e, float rot)
{
assert(e->body != NULL);
cpBodySetAngle(e->body, rot);
}
}
void entity_set_pos(Entity* e, V2 pos)
{
@ -270,12 +270,14 @@ void create_rectangle_shape(GameState* gs, Entity* e, Entity* parent, V2 pos, V2
cpSpaceAddShape(gs->space, e->shape);
}
#define PLAYER_SHAPE_FILTER cpShapeFilterNew(CP_NO_GROUP, PLAYERS, CP_ALL_CATEGORIES)
void create_player(GameState* gs, Entity* e)
{
e->is_player = true;
create_body(gs, e);
create_rectangle_shape(gs, e, e, (V2) { 0 }, V2scale(PLAYER_SIZE, 0.5f), PLAYER_MASS);
cpShapeSetFilter(e->shape, cpShapeFilterNew(CP_NO_GROUP, PLAYERS, CP_ALL_CATEGORIES));
cpShapeSetFilter(e->shape, PLAYER_SHAPE_FILTER);
}
// box must be passed as a parameter as the box added to chipmunk uses this pointer in its
@ -653,7 +655,7 @@ void ser_var(SerState* ser, char* var_pointer, size_t var_size, const char* name
{
printf("%s:%d | Expected variable %s but got %sn\n", file, line, var_name, read_name);
*(char*)NULL = 0;
}
}
}
#endif
for (int b = 0; b < var_size; b++)
@ -668,6 +670,7 @@ void ser_var(SerState* ser, char* var_pointer, size_t var_size, const char* name
#define SER_VAR_NAME(var_pointer, name) ser_var(ser, (char*)var_pointer, sizeof(*var_pointer), name, __FILE__, __LINE__)
#define SER_VAR(var_pointer) SER_VAR_NAME(var_pointer, #var_pointer)
// @Robust probably get rid of this as separate function, just use SER_VAR
void ser_V2(SerState* ser, V2* var)
{
SER_VAR(&var->x);
@ -739,9 +742,10 @@ void ser_entity(SerState* ser, GameState* gs, Entity* e)
if (has_shape)
{
SER_VAR(&e->shape_size);
ser_V2(ser, &e->shape_size);
ser_entityid(ser, &e->shape_parent_entity);
Entity* parent = get_entity(gs, e->shape_parent_entity);
assert(parent != NULL);
V2 shape_pos;
if (ser->serializing)
@ -753,14 +757,18 @@ void ser_entity(SerState* ser, GameState* gs, Entity* e)
shape_mass = entity_shape_mass(e);
SER_VAR(&shape_mass);
Entity* parent = get_entity(gs, e->shape_parent_entity);
if (parent == NULL)
cpShapeFilter filter;
if (ser->serializing)
{
printf("Null shape parent\n");
filter = cpShapeGetFilter(e->shape);
}
SER_VAR(&filter.categories);
SER_VAR(&filter.group);
SER_VAR(&filter.mask);
if (!ser->serializing)
{
create_rectangle_shape(gs, e, parent, shape_pos, e->shape_size, shape_mass);
cpShapeSetFilter(e->shape, filter);
}
}
@ -789,6 +797,7 @@ void ser_entity(SerState* ser, GameState* gs, Entity* e)
SER_VAR(&e->thrust);
SER_VAR(&e->wanted_thrust);
SER_VAR(&e->energy_used);
SER_VAR(&e->sun_amount);
ser_entityid(ser, &e->piloted_by);
}
}
@ -828,19 +837,13 @@ void ser_server_to_client(SerState* ser, ServerToClient* s)
Entity* e = &gs->entities[i];
if (e->exists)
{
if (e->is_player)
{
SER_VAR(&entities_done);
SER_VAR(&i);
ser_entity(ser, gs, e);
}
else if (e->is_grid)
SER_VAR(&entities_done);
SER_VAR(&i);
ser_entity(ser, gs, e);
if (e->is_grid)
{
// serialize boxes always after bodies, so that by the time the boxes
// are loaded in the parent body is loaded in and can be referenced.
SER_VAR(&entities_done);
SER_VAR(&i);
ser_entity(ser, gs, e);
BOXES_ITER(gs, cur, e)
{
EntityID cur_id = get_id(gs, cur);
@ -986,6 +989,20 @@ V2 get_world_hand_pos(GameState* gs, InputFrame* input, Entity* player)
}
}
// return true if used the energy
bool possibly_use_energy(GameState* gs, Entity* grid, float wanted_energy)
{
BOXES_ITER(gs, possible_battery, grid)
{
if (possible_battery->box_type == BoxBattery && (BATTERY_CAPACITY - possible_battery->energy_used) > wanted_energy)
{
possible_battery->energy_used += wanted_energy;
return true;
}
}
return false;
}
void process(GameState* gs, float dt)
{
assert(gs->space != NULL);
@ -1007,13 +1024,13 @@ void process(GameState* gs, float dt)
player->entity = get_id(gs, p);
cpVect pos = v2_to_cp(V2sub(entity_pos(p), SUN_POS));
cpFloat r = cpvlength(pos);
cpFloat v = cpfsqrt(SUN_GRAVITY_STRENGTH/ r) / r;
cpFloat v = cpfsqrt(SUN_GRAVITY_STRENGTH / r) / r;
cpBodySetVelocity(p->body, cpvmult(cpvperp(pos), v));
}
assert(p->is_player);
#ifdef INFINITE_RESOURCES
p->spice_taken_away = 0.0f;
p->spice_taken_away = 0.0f;
#endif
// update gold win condition
if (V2length(V2sub(cp_to_v2(cpBodyGetPosition(p->body)), gs->goldpos)) < GOLD_COLLECT_RADIUS)
@ -1072,7 +1089,7 @@ void process(GameState* gs, float dt)
if (piloting_seat == NULL)
{
cpShapeSetFilter(p->shape, CP_SHAPE_FILTER_ALL);
cpShapeSetFilter(p->shape, PLAYER_SHAPE_FILTER);
cpBodyApplyForceAtWorldPoint(p->body, v2_to_cp(V2scale(player->input.movement, PLAYER_JETPACK_FORCE)), cpBodyGetPosition(p->body));
p->spice_taken_away += movement_strength * dt * PLAYER_JETPACK_SPICE_PER_SECOND;
}
@ -1117,8 +1134,8 @@ void process(GameState* gs, float dt)
{
Entity* cur_box = cp_shape_entity(nearest);
Entity* cur_grid = cp_body_entity(cpShapeGetBody(nearest));
p->spice_taken_away -= SPICE_PER_BLOCK*((BATTERY_CAPACITY - cur_box->energy_used)/BATTERY_CAPACITY);
grid_remove_box(gs, cur_grid, cur_box);
p->spice_taken_away -= 0.1f;
}
else if (target_grid == NULL)
{
@ -1140,7 +1157,7 @@ void process(GameState* gs, float dt)
grid_correct_for_holes(gs, target_grid); // no holey ship for you!
new_box->box_type = player->input.build_type;
new_box->compass_rotation = player->input.build_rotation;
p->spice_taken_away += 0.1f;
p->spice_taken_away += SPICE_PER_BLOCK;
}
}
#endif
@ -1161,7 +1178,7 @@ void process(GameState* gs, float dt)
if (e->body != NULL)
{
cpVect p = cpvsub(cpBodyGetPosition(e->body),v2_to_cp(SUN_POS));
cpVect p = cpvsub(cpBodyGetPosition(e->body), v2_to_cp(SUN_POS));
cpFloat sqdist = cpvlengthsq(p);
if (sqdist < (SUN_RADIUS * SUN_RADIUS))
{
@ -1182,20 +1199,52 @@ void process(GameState* gs, float dt)
}
if (e->is_grid)
{
// calculate how much energy solar panels provide
float energy_to_add = 0.0f;
BOXES_ITER(gs, cur, e)
{
if (cur->box_type == BoxSolarPanel) {
cur->sun_amount = clamp01(V2dot(box_facing_vector(cur), V2normalize(V2sub(SUN_POS, box_pos(cur)))));
energy_to_add += cur->sun_amount * SOLAR_ENERGY_PER_SECOND * dt;
}
}
// apply all of the energy to all connected batteries
BOXES_ITER(gs, cur, e)
{
if (energy_to_add <= 0.0f)
break;
if (cur->box_type == BoxBattery)
{
float 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;
energy_to_add -= energy_sucked_up_by_battery;
}
assert(energy_to_add >= 0.0f);
}
// use the energy, stored in the batteries, in various boxes
BOXES_ITER(gs, cur, e)
{
if (cur->box_type == BoxThruster)
{
float energy_to_consume = cur->wanted_thrust * THRUSTER_ENERGY_USED_PER_SECOND * dt;
cur->thrust = 0.0f;
BOXES_ITER(gs, possible_battery, e)
if (possibly_use_energy(gs, e, energy_to_consume))
{
cur->thrust = cur->wanted_thrust;
cpBodyApplyForceAtWorldPoint(e->body, v2_to_cp(thruster_force(cur)), v2_to_cp(box_pos(cur)));
}
}
if (cur->box_type == BoxCockpit)
{
Entity* potential_pilot = get_entity(gs, cur->piloted_by);
if (potential_pilot != NULL && potential_pilot->spice_taken_away)
{
if (possible_battery->box_type == BoxBattery && (1.0f - possible_battery->energy_used) > energy_to_consume)
float energy_to_recharge = min(potential_pilot->spice_taken_away, PLAYER_ENERGY_RECHARGE_PER_SECOND * dt);
if (possibly_use_energy(gs, e, energy_to_recharge))
{
possible_battery->energy_used += energy_to_consume;
cur->thrust = cur->wanted_thrust;
cpBodyApplyForceAtWorldPoint(e->body, v2_to_cp(thruster_force(cur)), v2_to_cp(box_pos(cur)));
break;
potential_pilot->spice_taken_away -= energy_to_recharge;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

@ -74,6 +74,10 @@ static struct BoxInfo {
.type = BoxBattery,
.image_path = "loaded/battery.png",
},
{
.type = BoxSolarPanel,
.image_path = "loaded/solarpanel.png",
},
{
.type = BoxCockpit,
.image_path = "loaded/cockpit.png",
@ -705,7 +709,7 @@ frame(void)
float cur_alpha = sgp_get_color().a;
Color from = WHITE;
Color to = colhex(255, 0, 0);
Color result = Collerp(from, to, b->energy_used);
Color result = Collerp(from, to, b->energy_used/BATTERY_CAPACITY);
sgp_set_color(result.r, result.g, result.b, cur_alpha);
}
transform_scope
@ -741,6 +745,14 @@ frame(void)
draw_texture_centered(box_pos(b), BOX_SIZE);
sgp_reset_image(0);
if (b->box_type == BoxSolarPanel)
{
Color to_set = colhexcode(0xeb9834);
to_set.a = b->sun_amount*0.5f;
set_color(to_set);
draw_color_rect_centered(box_pos(b), BOX_SIZE);
}
sgp_set_color(0.5f, 0.1f, 0.1f, b->damage);
draw_color_rect_centered(box_pos(b), BOX_SIZE);
}

@ -14,10 +14,14 @@
#define THRUSTER_FORCE 4.0f
#define THRUSTER_ENERGY_USED_PER_SECOND 0.05f
#define VISION_RADIUS 16.0f
#define MAX_BYTES_SIZE 2048 * 2 // maximum size of gamestate buffer
#define MAX_BYTES_SIZE 1024 * 8 // maximum size of gamestate buffer
#define SUN_RADIUS 10.0f
#define SUN_POS ((V2){50.0f,0.0f})
#define SUN_GRAVITY_STRENGTH (5.0e3f)
#define SOLAR_ENERGY_PER_SECOND 0.02f
#define SPICE_PER_BLOCK 0.1f
#define BATTERY_CAPACITY SPICE_PER_BLOCK
#define PLAYER_ENERGY_RECHARGE_PER_SECOND 0.1f
#define TIMESTEP (1.0f / 60.0f) // not required to simulate at this, but this defines what tick the game is on
#define TIME_BETWEEN_INPUT_PACKETS (1.0f / 20.0f)
@ -77,6 +81,7 @@ enum BoxType
BoxThruster,
BoxBattery,
BoxCockpit,
BoxSolarPanel,
BoxLast,
};
@ -156,6 +161,7 @@ typedef struct Entity
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
float energy_used; // battery
float sun_amount; // solar panel, between 0 and 1
EntityID piloted_by;
} Entity;

Loading…
Cancel
Save