diff --git a/gamestate.c b/gamestate.c index 3abbba0..92f7932 100644 --- a/gamestate.c +++ b/gamestate.c @@ -473,9 +473,9 @@ static cpBool on_damage(cpArbiter* arb, cpSpace* space, cpDataPointer userData) float damage = V2length(cp_to_v2(cpArbiterTotalImpulse(arb))) * COLLISION_DAMAGE_SCALING; if (entity_a->is_box && entity_a->box_type == BoxExplosive) - entity_a->damage += 2.0f*EXPLOSION_DAMAGE_THRESHOLD; + entity_a->damage += 2.0f * EXPLOSION_DAMAGE_THRESHOLD; if (entity_b->is_box && entity_b->box_type == BoxExplosive) - entity_b->damage += 2.0f*EXPLOSION_DAMAGE_THRESHOLD; + entity_b->damage += 2.0f * EXPLOSION_DAMAGE_THRESHOLD; if (damage > 0.05f) { @@ -809,6 +809,7 @@ void ser_entity(SerState* ser, GameState* gs, Entity* e) ser_entityid(ser, &e->next_box); ser_entityid(ser, &e->prev_box); SER_VAR(&e->compass_rotation); + SER_VAR(&e->indestructible); SER_VAR(&e->thrust); SER_VAR(&e->wanted_thrust); SER_VAR(&e->energy_used); @@ -1054,6 +1055,45 @@ void entity_ensure_in_orbit(Entity* e) cpBodySetVelocity(e->body, cpvmult(cpvperp(pos), v)); } +EntityID create_spacestation(GameState* gs) +{ +#define BOX_AT_TYPE(grid, pos, type) { Entity* box = new_entity(gs); box_create(gs, box, grid, pos); box->box_type = type; box->indestructible = indestructible; } +#define BOX_AT(grid, pos) BOX_AT_TYPE(grid, pos, BoxHullpiece) + + bool indestructible = false; + Entity* grid = new_entity(gs); + grid_create(gs, grid); + entity_set_pos(grid, (V2) { -150.0f, 0.0f }); + entity_ensure_in_orbit(grid); + Entity* explosion_box = new_entity(gs); + box_create(gs, explosion_box, grid, (V2) { 0 }); + explosion_box->is_explosion_unlock = true; + BOX_AT_TYPE(grid, ((V2) { BOX_SIZE, 0 }), BoxExplosive); + BOX_AT_TYPE(grid, ((V2) { BOX_SIZE*2, 0 }), BoxHullpiece); + BOX_AT_TYPE(grid, ((V2) { BOX_SIZE*3, 0 }), BoxHullpiece); + BOX_AT_TYPE(grid, ((V2) { BOX_SIZE*4, 0 }), BoxHullpiece); + + indestructible = true; + for (float y = -BOX_SIZE * 5.0; y <= BOX_SIZE * 5.0; y += BOX_SIZE) + { + 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) + { + BOX_AT_TYPE(grid, ((V2) { x, BOX_SIZE*5.0 }), BoxHullpiece); + BOX_AT_TYPE(grid, ((V2) { x, -BOX_SIZE*5.0 }), BoxHullpiece); + } + indestructible = false; + BOX_AT_TYPE(grid, ((V2) { -BOX_SIZE*6.0, BOX_SIZE*5.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*1.0 }), BoxExplosive); + 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 process(GameState* gs, float dt) { assert(gs->space != NULL); @@ -1178,9 +1218,12 @@ void process(GameState* gs, float dt) if (nearest != NULL) { Entity* cur_box = cp_shape_entity(nearest); - Entity* cur_grid = cp_body_entity(cpShapeGetBody(nearest)); - p->damage -= DAMAGE_TO_PLAYER_PER_BLOCK * ((BATTERY_CAPACITY - cur_box->energy_used) / BATTERY_CAPACITY); - grid_remove_box(gs, cur_grid, cur_box); + if (!cur_box->indestructible) + { + Entity* cur_grid = cp_body_entity(cpShapeGetBody(nearest)); + p->damage -= DAMAGE_TO_PLAYER_PER_BLOCK * ((BATTERY_CAPACITY - cur_box->energy_used) / BATTERY_CAPACITY); + grid_remove_box(gs, cur_grid, cur_box); + } } else if (target_grid == NULL) { @@ -1215,6 +1258,11 @@ void process(GameState* gs, float dt) p->damage = clamp01(p->damage); } + if(get_entity(gs, gs->cur_spacestation) == NULL) + { + gs->cur_spacestation = create_spacestation(gs); + } + // process entities for (size_t i = 0; i < gs->cur_next_entity; i++) { Entity* e = &gs->entities[i]; diff --git a/main.c b/main.c index 90684ba..936f569 100644 --- a/main.c +++ b/main.c @@ -791,6 +791,10 @@ frame(void) img = image_medbay_used; } sgp_set_image(0, img); + if (b->indestructible) + { + sgp_set_color(0.2f, 0.2f, 0.2f, 1.0f); + } draw_texture_centered(entity_pos(b), BOX_SIZE); sgp_reset_image(0); diff --git a/server.c b/server.c index 4b8317e..af7d8ae 100644 --- a/server.c +++ b/server.c @@ -21,18 +21,8 @@ void server(void* data) initialize(&gs, entity_data, entities_size); Log("Allocated %zu bytes for entities\n", entities_size); -#define BOX_AT(grid, pos) { Entity* box = new_entity(&gs); box_create(&gs, box, grid, pos); } - // space station with explosion unlock - if (true) - { - Entity* grid = new_entity(&gs); - grid_create(&gs, grid); - entity_set_pos(grid, (V2) { -10.0f, 0.0f }); - entity_ensure_in_orbit(grid); - Entity* explosion_box = new_entity(&gs); - box_create(&gs, explosion_box, grid, (V2) { 0 }); - explosion_box->is_explosion_unlock = true; - } +#define BOX_AT_TYPE(grid, pos, type) { Entity* box = new_entity(&gs); box_create(&gs, box, grid, pos); box->box_type = type; } +#define BOX_AT(grid, pos) BOX_AT_TYPE(grid, pos, BoxHullpiece) // one box policy if (false) diff --git a/types.h b/types.h index 8bbdee7..9401952 100644 --- a/types.h +++ b/types.h @@ -6,6 +6,7 @@ #define PLAYER_SIZE ((V2){.x = BOX_SIZE, .y = BOX_SIZE}) #define PLAYER_MASS 0.5f #define PLAYER_JETPACK_FORCE 2.0f +// #define PLAYER_JETPACK_FORCE 20.0f #define PLAYER_JETPACK_SPICE_PER_SECOND 0.3f #define MAX_HAND_REACH 1.0f #define GOLD_COLLECT_RADIUS 0.3f @@ -174,6 +175,7 @@ typedef struct Entity EntityID next_box; EntityID prev_box; // doubly linked so can remove in middle of chain enum CompassRotation compass_rotation; + bool indestructible; 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 @@ -199,6 +201,8 @@ typedef struct GameState Player players[MAX_PLAYERS]; + EntityID cur_spacestation; + // Entity arena // ent:ity pointers can't move around because of how the physics engine handles user data. // if you really need this, potentially refactor to store entity IDs instead of pointers @@ -252,6 +256,7 @@ struct ClientToServer void server(void* data); // data parameter required from thread api... // gamestate +EntityID create_spacestation(GameState* gs); void initialize(struct GameState* gs, void* entity_arena, size_t entity_arena_size); void destroy(struct GameState* gs); void process(struct GameState* gs, float dt); // does in place