Compare commits

...

2 Commits

@ -177,12 +177,13 @@
<PreprocessorDefinitions>NDEBUG;RELEASE;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)\thirdparty\enet\include;$(ProjectDir)\thirdparty\Chipmunk2D\include\chipmunk;$(ProjectDir)\thirdparty;$(ProjectDir)\thirdparty\Chipmunk2D\include;$(ProjectDir)\thirdparty\minilzo;$(ProjectDir)\thirdparty\opus\include</AdditionalIncludeDirectories>
<OmitFramePointers>false</OmitFramePointers>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
<AdditionalDependencies>$(CoreLibraryDependencies);%(AdditionalDependencies);Ws2_32.lib;winmm.lib;$(ProjectDir)\thirdparty\opus\win32\VS2015\x64\Release\opus.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>

@ -4,7 +4,7 @@
<ShowAllFiles>false</ShowAllFiles>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerCommandArguments>--host</LocalDebuggerCommandArguments>
<LocalDebuggerCommandArguments>host=true</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug No Host|x64'">

@ -26,7 +26,7 @@
#define DEBUG_TOOLS
#define CHIPMUNK_INTEGRITY_CHECK
// #define FAT_THRUSTERS
#define NO_GRAVITY
//#define NO_GRAVITY
// #define NO_SUNS
#else

Binary file not shown.

@ -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);
@ -666,7 +687,7 @@ void box_add_to_boxes(GameState *gs, Entity *grid, Entity *box_to_add)
// box must be passed as a parameter as the box added to chipmunk uses this pointer in its
// user data. pos is in local coordinates. Adds the box to the grid's chain of boxes
// Must pass in a type so it knows what filter to give the collision shape
void box_create(GameState *gs, Entity *new_box, Entity *grid, cpVect pos, enum BoxType type)
void create_box(GameState *gs, Entity *new_box, Entity *grid, cpVect pos, enum BoxType type)
{
new_box->is_box = true;
flight_assert(gs->space != NULL);
@ -951,7 +972,7 @@ static void grid_correct_for_holes(GameState *gs, struct Entity *grid)
cpShapeSetUserData(cur->shape, NULL);
cur->shape = NULL;
box_create(gs, cur, new_grid, new_shape_position, cur->box_type); // destroys next/prev fields on cur
create_box(gs, cur, new_grid, new_shape_position, cur->box_type); // destroys next/prev fields on cur
cur = next;
}
@ -1604,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;
}
@ -2306,7 +2362,7 @@ void create_bomb_station(GameState *gs, cpVect pos, enum BoxType platonic_type)
#define BOX_AT_TYPE(grid, pos, type) \
{ \
Entity *box = new_entity(gs); \
box_create(gs, box, grid, pos, type); \
create_box(gs, box, grid, pos, type); \
box->compass_rotation = rot; \
box->indestructible = indestructible; \
}
@ -2317,7 +2373,7 @@ void create_bomb_station(GameState *gs, cpVect pos, enum BoxType platonic_type)
grid_create(gs, grid);
entity_set_pos(grid, pos);
Entity *platonic_box = new_entity(gs);
box_create(gs, platonic_box, grid, (cpVect){0}, platonic_type);
create_box(gs, platonic_box, grid, (cpVect){0}, platonic_type);
platonic_box->is_platonic = true;
BOX_AT_TYPE(grid, ((cpVect){BOX_SIZE, 0}), BoxExplosive);
BOX_AT_TYPE(grid, ((cpVect){BOX_SIZE * 2, 0}), BoxHullpiece);
@ -2355,7 +2411,7 @@ void create_hard_shell_station(GameState *gs, cpVect pos, enum BoxType platonic_
grid_create(gs, grid);
entity_set_pos(grid, pos);
Entity *platonic_box = new_entity(gs);
box_create(gs, platonic_box, grid, (cpVect){0}, platonic_type);
create_box(gs, platonic_box, grid, (cpVect){0}, platonic_type);
platonic_box->is_platonic = true;
BOX_AT_TYPE(grid, ((cpVect){BOX_SIZE * 2, 0}), BoxHullpiece);
BOX_AT_TYPE(grid, ((cpVect){BOX_SIZE * 3, 0}), BoxHullpiece);
@ -2432,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;
{
@ -2456,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);
@ -2793,7 +2872,7 @@ void process(struct GameState *gs, double dt)
#if 1 // building
if (player->input.dobuild)
{
player->input.dobuild = false; // handle the input. if didn't do this, after destruction of hovered box, would try to build on it again the next frame
player->input.dobuild = false; // handle the input. if didn't do this, after destruction of hovered box, would try to build on it again the next frame. @Robust handle the input in one place
cpPointQueryInfo info = {0};
cpVect world_build = world_hand_pos;
@ -2830,7 +2909,7 @@ void process(struct GameState *gs, double dt)
created_box_position = grid_world_to_local(target_grid, world_build);
}
Entity *new_box = new_entity(gs);
box_create(gs, new_box, target_grid, created_box_position, player->input.build_type);
create_box(gs, new_box, target_grid, created_box_position, player->input.build_type);
new_box->owning_squad = player->squad;
grid_correct_for_holes(gs, target_grid); // no holey ship for you!
new_box->compass_rotation = player->input.build_rotation;
@ -3097,7 +3176,7 @@ void process(struct GameState *gs, double dt)
enum CompassRotation new_rotation = facing_vector_to_compass(from_grid, other_grid, box_facing_vector(cur));
cur->compass_rotation = new_rotation;
cpVect new_cur_pos = grid_snapped_box_pos(from_grid, cpvadd(snap_movement_vect, world));
box_create(gs, cur, from_grid, grid_world_to_local(from_grid, new_cur_pos), cur->box_type); // destroys next/prev fields on cur
create_box(gs, cur, from_grid, grid_world_to_local(from_grid, new_cur_pos), cur->box_type); // destroys next/prev fields on cur
flight_assert(box_grid(cur) == box_grid(from_merge));
cur = next;
}
@ -3413,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);
}
}
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

@ -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");
}

@ -99,7 +99,7 @@ void server(void *info_raw)
#define BOX_AT_TYPE(grid, pos, type) \
{ \
Entity *box = new_entity(&gs); \
box_create(&gs, box, grid, pos); \
create_box(&gs, box, grid, pos); \
box->box_type = type; \
}
#define BOX_AT(grid, pos) BOX_AT_TYPE(grid, pos, BoxHullpiece)

@ -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,
};
@ -277,7 +280,7 @@ typedef struct Entity
double damage; // used by box, player, and orb
cpBody *body; // used by grid, player, and box
cpShape *shape; // must be a box so shape_size can be set appropriately, and serialized
cpShape *shape; // see notes on serializing the shape
// players and boxes can be cloaked
// If this is within 2 timesteps of the current game time, the entity is invisible.
@ -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
@ -562,7 +568,7 @@ LauncherTarget missile_launcher_target(GameState *gs, Entity *launcher);
// grid
void grid_create(struct GameState *gs, Entity *e);
void box_create(struct GameState *gs, Entity *new_box, Entity *grid, cpVect pos, enum BoxType type);
void create_box(struct GameState *gs, Entity *new_box, Entity *grid, cpVect pos, enum BoxType type);
Entity *box_grid(Entity *box);
cpVect grid_com(Entity *grid);
cpVect grid_vel(Entity *grid);

Loading…
Cancel
Save