diff --git a/Flight.vcxproj b/Flight.vcxproj index 26ad283..3b33e41 100644 --- a/Flight.vcxproj +++ b/Flight.vcxproj @@ -177,12 +177,13 @@ NDEBUG;RELEASE;_CONSOLE;%(PreprocessorDefinitions) true $(ProjectDir)\thirdparty\enet\include;$(ProjectDir)\thirdparty\Chipmunk2D\include\chipmunk;$(ProjectDir)\thirdparty;$(ProjectDir)\thirdparty\Chipmunk2D\include;$(ProjectDir)\thirdparty\minilzo;$(ProjectDir)\thirdparty\opus\include + false Console true true - true + DebugFull $(CoreLibraryDependencies);%(AdditionalDependencies);Ws2_32.lib;winmm.lib;$(ProjectDir)\thirdparty\opus\win32\VS2015\x64\Release\opus.lib diff --git a/Flight.vcxproj.user b/Flight.vcxproj.user index a8c5a48..840ad31 100644 --- a/Flight.vcxproj.user +++ b/Flight.vcxproj.user @@ -4,7 +4,7 @@ false - --host + host=true WindowsLocalDebugger diff --git a/buildsettings.h b/buildsettings.h index 875321d..455f21e 100644 --- a/buildsettings.h +++ b/buildsettings.h @@ -26,7 +26,7 @@ #define DEBUG_TOOLS #define CHIPMUNK_INTEGRITY_CHECK // #define FAT_THRUSTERS -#define NO_GRAVITY +//#define NO_GRAVITY // #define NO_SUNS #else diff --git a/flight.rdbg b/flight.rdbg index 2ea4401..41aeac4 100644 Binary files a/flight.rdbg and b/flight.rdbg differ diff --git a/gamestate.c b/gamestate.c index 88a73d5..e5fb6d3 100644 --- a/gamestate.c +++ b/gamestate.c @@ -407,6 +407,13 @@ LauncherTarget missile_launcher_target(GameState *gs, Entity *launcher) return (LauncherTarget){.target_found = target_found, .facing_angle = to_face}; } +void destroy_constraints(cpBody *body, cpConstraint *constraint, void *data) +{ + ((Entity*)cpConstraintGetUserData(constraint))->landed_constraint = NULL; + cpSpaceRemoveConstraint(cpBodyGetSpace(body), constraint); + cpConstraintFree(constraint); +} + void destroy_child_shape(cpBody *body, cpShape *shape, void *data) { GameState *gs = (GameState *)data; @@ -447,14 +454,22 @@ void entity_memory_free(GameState *gs, Entity *e) cpShapeFree(e->shape); e->shape = NULL; } + if (e->landed_constraint != NULL) + { + cpSpaceRemoveConstraint(gs->space, e->landed_constraint); + cpConstraintFree(e->landed_constraint); + e->landed_constraint = NULL; + } if (e->body != NULL) { + // need to do this here because body which constraint is attached to can be destroyed + // NOT TRUE: can't do this here because the handle to the constraint cannot be set to NULL. Constraints are freed by the entities that own them + cpBodyEachConstraint(e->body, destroy_constraints, NULL); cpBodyEachShape(e->body, destroy_child_shape, (void *)gs); cpSpaceRemoveBody(gs->space, e->body); cpBodyFree(e->body); e->body = NULL; } - Entity *front_of_free_list = get_entity(gs, gs->free_list); if (front_of_free_list != NULL) flight_assert(!front_of_free_list->exists); @@ -518,6 +533,12 @@ void create_body(GameState *gs, Entity *e) cpBodySetUserData(e->body, (void *)e); } +// must always call this after creating a constraint +void on_create_constraint(Entity *e, cpConstraint* c) +{ + cpConstraintSetUserData(c, (cpDataPointer)e); +} + cpVect player_vel(GameState *gs, Entity *player) { flight_assert(player->is_player); @@ -627,8 +648,6 @@ void create_player(Player *player) #endif } - - void create_orb(GameState *gs, Entity *e) { create_body(gs, e); @@ -1606,6 +1625,41 @@ SerMaybeFailure ser_entity(SerState *ser, GameState *gs, Entity *e) case BoxMissileLauncher: SER_MAYBE_RETURN(ser_f(ser, &e->missile_construction_charge)); break; + case BoxLandingGear: + { + bool is_null = e->landed_constraint == NULL; + SER_VAR(&is_null); + if (!is_null) + { + EntityID from = {0}; + EntityID to = {0}; + cpVect pin = {0}; + if (ser->serializing) + { + from = get_id(gs, cp_body_entity(cpConstraintGetBodyA(e->landed_constraint))); + to = get_id(gs, cp_body_entity(cpConstraintGetBodyB(e->landed_constraint))); + pin = cpPivotJointGetAnchorA(e->landed_constraint); + } + SER_MAYBE_RETURN(ser_entityid(ser, &from)); + SER_MAYBE_RETURN(ser_entityid(ser, &to)); + SER_MAYBE_RETURN(ser_V2(ser, &pin)); + if (!ser->serializing) + { + Entity *from_entity = get_entity(gs, from); + Entity *to_entity = get_entity(gs, to); + if (from_entity == NULL || to_entity == NULL) + { + } + else + { + e->landed_constraint = cpPivotJointNew(from_entity->body, to_entity->body, pin); + cpSpaceAddConstraint(gs->space, e->landed_constraint); + on_create_constraint(e, e->landed_constraint); + } + } + } + break; + } default: break; } @@ -2434,7 +2488,7 @@ void create_initial_world(GameState *gs) create_hard_shell_station(gs, (cpVect){-5.0, 5.0}, BoxCloaking); #endif -#if 1 // scanner box +#if 0 // scanner box bool indestructible = false; enum CompassRotation rot = Right; { @@ -2458,6 +2512,29 @@ void create_initial_world(GameState *gs) #endif +#if 1 // landing gear box + bool indestructible = false; + cpVect from = cpv(4.0 * BOX_SIZE, 0.0); + enum CompassRotation rot = Right; + { + Entity *grid = new_entity(gs); + grid_create(gs, grid); + entity_set_pos(grid, from); + BOX_AT_TYPE(grid, ((cpVect){0.0, 0.0}), BoxLandingGear); + // BOX_AT(grid, ((cpVect){0.0, -BOX_SIZE})); + // BOX_AT_TYPE(grid, ((cpVect){BOX_SIZE, 0.0}), BoxMerge); + entity_ensure_in_orbit(gs, grid); + cpBodySetVelocity(grid->body, cpv(0.1, 0.0)); + } + { + Entity *grid = new_entity(gs); + grid_create(gs, grid); + entity_set_pos(grid, cpvadd(from, cpv(2.0 * BOX_SIZE, 0.0))); + BOX_AT_TYPE(grid, ((cpVect){0.0, 0.0}), BoxHullpiece); + entity_ensure_in_orbit(gs, grid); + } +#endif + #if 0 // merge box bool indestructible = false; double theta = deg2rad(65.0); @@ -3415,6 +3492,27 @@ void process(struct GameState *gs, double dt) cur_box->scanner_head_rotate += cur_box->scanner_head_rotate_speed * dt; cur_box->scanner_head_rotate = fmod(cur_box->scanner_head_rotate, 2.0 * PI); } + if (cur_box->box_type == BoxLandingGear) + { + if (cur_box->landed_constraint == NULL) + { + cpVect along = box_facing_vector(cur_box); + cpVect from = cpvadd(entity_pos(cur_box), cpvmult(along, BOX_SIZE / 2.0 + 0.03)); + cpVect to = cpvadd(from, cpvmult(along, LANDING_GEAR_MAX_DIST)); + + cpSegmentQueryInfo query_result = {0}; + cpShape *found = cpSpaceSegmentQueryFirst(gs->space, from, to, 0.0, FILTER_DEFAULT, &query_result); + if (found != NULL && cpShapeGetBody(found) != box_grid(cur_box)->body) + { + cpVect anchor = cpvadd(entity_pos(cur_box), cpvmult(along, BOX_SIZE / 2.0)); + cpBody *a = box_grid(cur_box)->body; + cpBody *b = cpShapeGetBody(found); + cur_box->landed_constraint = cpPivotJointNew(a, b, anchor); + cpSpaceAddConstraint(gs->space, cur_box->landed_constraint); + on_create_constraint(cur_box, cur_box->landed_constraint); + } + } + } } } } diff --git a/loaded/landing_gear.png b/loaded/landing_gear.png new file mode 100644 index 0000000..8a6e462 Binary files /dev/null and b/loaded/landing_gear.png differ diff --git a/main.c b/main.c index 6d6e269..eb77b5c 100644 --- a/main.c +++ b/main.c @@ -139,6 +139,7 @@ static sg_image image_noenergy; static sg_image image_orb; static sg_image image_orb_frozen; static sg_image image_radardot; +static sg_image image_landing_gear; static sg_image image_pip; static sg_image fire_rendertarget; @@ -232,6 +233,10 @@ static struct BoxInfo .type = BoxMerge, .image_path = "loaded/merge.png", }, + { + .type = BoxLandingGear, + .image_path = "loaded/landing_gear.png", + }, }; // suppress compiler warning about ^^ above used in floating point context #define ARRLENF(arr) ((float)sizeof(arr) / sizeof(*arr)) @@ -852,6 +857,7 @@ static void init(void) image_orb = load_image("loaded/orb.png"); image_orb_frozen = load_image("loaded/orb_frozen.png"); image_radardot = load_image("loaded/radardot.png"); + image_landing_gear = load_image("loaded/landing_gear.png"); image_pip = load_image("loaded/pip.png"); } diff --git a/types.h b/types.h index aabc873..3594cc6 100644 --- a/types.h +++ b/types.h @@ -58,6 +58,8 @@ #define THRUSTER_ENERGY_USED_PER_SECOND 0.005 #define THRUSTER_DAMAGE_PER_SEC 2.0 +#define LANDING_GEAR_MAX_DIST (BOX_SIZE * 0.25) + #define GYROSCOPE_ENERGY_USED_PER_SECOND 0.005f #define GYROSCOPE_TORQUE 1.5f #define GYROSCOPE_PROPORTIONAL_INERTIAL_RESPONSE 0.7 // between 0-1. How strongly responds to rotation, to stop the rotation @@ -189,6 +191,7 @@ enum BoxType BoxCloaking, BoxMissileLauncher, BoxMerge, + BoxLandingGear, BoxLast, }; @@ -374,6 +377,9 @@ typedef struct Entity double scanner_head_rotate_speed; // not serialized, cosmetic double scanner_head_rotate; + // landing gear only + cpConstraint *landed_constraint; // when null is landed + PlatonicDetection detected_platonics[SCANNER_MAX_PLATONICS]; // intensity of 0.0 means undetected struct ScannerPoint