diff --git a/gamestate.c b/gamestate.c index 270887e..4b8d30b 100644 --- a/gamestate.c +++ b/gamestate.c @@ -324,6 +324,7 @@ void ser_grid(char **out, struct Grid *g) ser_int(out, g->boxes[i].type); // @Robust separate enum serialization that checks for out of bounds enum ser_int(out, g->boxes[i].rotation); ser_float(out, g->boxes[i].thrust); + ser_float(out, g->boxes[i].energy_used); ser_float(out, g->boxes[i].damage); } } @@ -362,6 +363,7 @@ void des_grid(char **in, struct Grid *g, struct GameState *gs) des_int(in, (int *)&g->boxes[i].type); des_int(in, (int *)&g->boxes[i].rotation); des_float(in, &g->boxes[i].thrust); + des_float(in, &g->boxes[i].energy_used); des_float(in, &g->boxes[i].damage); } } @@ -672,8 +674,7 @@ void process(struct GameState *gs, float dt) V2 target_new_pos = V2lerp(p->pos, grid_com(g), dt * 20.0f); p->vel = V2scale(V2sub(target_new_pos, p->pos), 1.0f / dt); // set vel correctly so newly built grids have the correct velocity copied from it - // set thruster forces from movement - float thruster_spice_consumption = 0.0f; + // set thruster thrust from movement { V2 target_direction = {0}; if (V2length(p->input.movement) > 0.0f) @@ -688,14 +689,12 @@ void process(struct GameState *gs, float dt) float wanted_thrust = -V2dot(target_direction, thruster_direction(&g->boxes[ii])); wanted_thrust = clamp01(wanted_thrust); - thruster_spice_consumption += wanted_thrust; + g->boxes[ii].thrust = wanted_thrust; } } - // cpBodyApplyForceAtWorldPoint(g->body, v2_to_cp(V2scale(p->input.movement, 5.0f)), v2_to_cp(grid_com(g))); // bigger the ship, the more efficient the spice usage - p->spice_taken_away += dt * thruster_spice_consumption * THRUSTER_SPICE_PER_SECOND; } p->pos = V2add(p->pos, V2scale(p->vel, dt)); } @@ -775,12 +774,44 @@ void process(struct GameState *gs, float dt) for (int i = 0; i < MAX_GRIDS; i++) { SKIPNULL(gs->grids[i].body); + + struct Box *batteries[MAX_BOXES_PER_GRID] = {0}; + int cur_battery = 0; + for (int ii = 0; ii < MAX_BOXES_PER_GRID; ii++) + { + SKIPNULL(gs->grids[i].boxes[ii].shape); + if (gs->grids[i].boxes[ii].type == BoxBattery) + { + assert(cur_battery < MAX_BOXES_PER_GRID); + batteries[cur_battery] = &gs->grids[i].boxes[ii]; + cur_battery++; + } + } + int batteries_len = cur_battery; + + float thruster_energy_consumption_per_second = 0.0f; for (int ii = 0; ii < MAX_BOXES_PER_GRID; ii++) { SKIPNULL(gs->grids[i].boxes[ii].shape); if (gs->grids[i].boxes[ii].type == BoxThruster) { - cpBodyApplyForceAtWorldPoint(gs->grids[i].body, v2_to_cp(thruster_force(&gs->grids[i].boxes[ii])), v2_to_cp(box_pos(&gs->grids[i].boxes[ii]))); + float energy_to_consume = gs->grids[i].boxes[ii].thrust * THRUSTER_ENERGY_USED_PER_SECOND * dt; + struct Box *max_capacity_battery = NULL; + float max_capacity_battery_energy_used = 1.0f; + for (int iii = 0; iii < batteries_len; iii++) + { + if (batteries[iii]->energy_used < max_capacity_battery_energy_used) + { + max_capacity_battery = batteries[iii]; + max_capacity_battery_energy_used = batteries[iii]->energy_used; + } + } + + if (max_capacity_battery != NULL && (1.0f - max_capacity_battery->energy_used) > energy_to_consume) + { + max_capacity_battery->energy_used += energy_to_consume; + cpBodyApplyForceAtWorldPoint(gs->grids[i].body, v2_to_cp(thruster_force(&gs->grids[i].boxes[ii])), v2_to_cp(box_pos(&gs->grids[i].boxes[ii]))); + } } } } diff --git a/loaded/battery.png b/loaded/battery.png new file mode 100644 index 0000000..070dcb4 Binary files /dev/null and b/loaded/battery.png differ diff --git a/main.c b/main.c index a1bf25c..63a77c1 100644 --- a/main.c +++ b/main.c @@ -57,6 +57,10 @@ static struct BoxInfo { .type = BoxThruster, .image_path = "loaded/thruster.png", + }, + { + .type = BoxBattery, + .image_path = "loaded/battery.png", }}; const int boxes_len = sizeof(boxes) / sizeof(*boxes); @@ -192,13 +196,6 @@ static void drawbox(V2 boxpos, float rot, float damage, enum BoxType type, enum sgp_draw_textured_rect(boxpos.x - halfbox, boxpos.y - halfbox, BOX_SIZE, BOX_SIZE); sgp_reset_image(0); - /*sgp_draw_line(bpos.x - halfbox, bpos.y - halfbox, bpos.x - halfbox, bpos.y + halfbox); // left - sgp_draw_line(bpos.x - halfbox, bpos.y - halfbox, bpos.x + halfbox, bpos.y - halfbox); // top - sgp_draw_line(bpos.x + halfbox, bpos.y - halfbox, bpos.x + halfbox, bpos.y + halfbox); // right - sgp_draw_line(bpos.x - halfbox, bpos.y + halfbox, bpos.x + halfbox, bpos.y + halfbox); // bottom - sgp_draw_line(bpos.x - halfbox, bpos.y - halfbox, bpos.x + halfbox, bpos.y + halfbox); // diagonal - */ - if (damage > 0.0f) { sgp_set_color(0.5f, 0.1f, 0.1f, damage); @@ -553,7 +550,7 @@ static void frame(void) { SKIPNULL(g->boxes[ii].shape); struct Box *b = &g->boxes[ii]; - sgp_set_color(0.5f, 0.5f, 0.5f, 1.0f); + sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f); // debug draw force vectors for thrusters if (false) { @@ -563,6 +560,14 @@ static void frame(void) dbg_line(box_pos(b), V2add(box_pos(b), V2scale(thruster_force(b), -1.0f))); } } + if(b->type == BoxBattery) + { + float cur_alpha = sgp_get_color().a; + Color from = WHITE; + Color to = colhex(255, 0, 0); + Color result = Collerp(from, to, b->energy_used); + sgp_set_color(result.r, result.g, result.b, cur_alpha); + } drawbox(box_pos(b), grid_rotation(g), b->damage, b->type, b->rotation); } sgp_set_color(1.0f, 0.0f, 0.0f, 1.0f); diff --git a/thirdparty/sokol_gp.h b/thirdparty/sokol_gp.h index 103b117..15c6fb1 100644 --- a/thirdparty/sokol_gp.h +++ b/thirdparty/sokol_gp.h @@ -543,6 +543,7 @@ SOKOL_GP_API_DECL void sgp_reset_uniform(void); /* R SOKOL_GP_API_DECL void sgp_set_blend_mode(sgp_blend_mode blend_mode); /* Sets current blend mode. */ SOKOL_GP_API_DECL void sgp_reset_blend_mode(void); /* Resets current blend mode to default (no blending). */ SOKOL_GP_API_DECL void sgp_set_color(float r, float g, float b, float a); /* Sets current color modulation. */ +SOKOL_GP_API_DECL sgp_color sgp_get_color(); /* Gets the current color modulation */ SOKOL_GP_API_DECL void sgp_reset_color(void); /* Resets current color modulation to default (white). */ SOKOL_GP_API_DECL void sgp_set_image(int channel, sg_image image); /* Sets current bound texture in a texture channel. */ SOKOL_GP_API_DECL void sgp_unset_image(int channel); /* Remove current bound texture in a texture channel (no texture). */ @@ -1622,6 +1623,13 @@ void sgp_set_color(float r, float g, float b, float a) { } } +sgp_color sgp_get_color() +{ + SOKOL_ASSERT(_sgp.init_cookie == _SGP_INIT_COOKIE); + SOKOL_ASSERT(_sgp.cur_state > 0); + return _sgp.state.color; +} + void sgp_reset_color(void) { SOKOL_ASSERT(_sgp.init_cookie == _SGP_INIT_COOKIE); sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f); diff --git a/types.h b/types.h index c568304..2f57e85 100644 --- a/types.h +++ b/types.h @@ -9,7 +9,7 @@ #define MAX_BOXES_PER_GRID 32 #define BOX_MASS 1.0f #define THRUSTER_FORCE 4.0f -#define THRUSTER_SPICE_PER_SECOND 0.02f +#define THRUSTER_ENERGY_USED_PER_SECOND 0.05f #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) @@ -67,7 +67,8 @@ enum BoxType { BoxHullpiece, BoxThruster, - BoxLast + BoxBattery, + BoxLast, }; enum Rotation @@ -133,6 +134,9 @@ struct GameState // thruster float thrust; // must be between 0 and 1 + + // battery + float energy_used; // must be between 0 and 1 cpShape *shape; float damage;