Safe sun and delete at end of processing

main
Cameron Murphy Reikes 2 years ago
parent 3890722c65
commit 8ca9f2257e

@ -18,15 +18,15 @@
// Intensive profiling means profiling a lot of little tiny stuff. Not always enabled because tanks performance // Intensive profiling means profiling a lot of little tiny stuff. Not always enabled because tanks performance
// #define INTENSIVE_PROFILING // #define INTENSIVE_PROFILING
// #define DEBUG_RENDERING // #define DEBUG_RENDERING
// #define DEBUG_WORLD #define DEBUG_WORLD
// #define UNLOCK_ALL #define UNLOCK_ALL
#define TIME_BETWEEN_WORLD_SAVE 1000000.0f #define TIME_BETWEEN_WORLD_SAVE 1000000.0f
// #define TIME_BETWEEN_WORLD_SAVE 1.0f // #define TIME_BETWEEN_WORLD_SAVE 1.0f
// #define INFINITE_RESOURCES #define INFINITE_RESOURCES
#define DEBUG_TOOLS #define DEBUG_TOOLS
#define CHIPMUNK_INTEGRITY_CHECK #define CHIPMUNK_INTEGRITY_CHECK
// #define FAT_THRUSTERS // #define FAT_THRUSTERS
// #define NO_GRAVITY #define NO_GRAVITY
// #define NO_SUNS // #define NO_SUNS
#else #else

Binary file not shown.

@ -407,70 +407,64 @@ LauncherTarget missile_launcher_target(GameState *gs, Entity *launcher)
return (LauncherTarget){.target_found = target_found, .facing_angle = to_face}; return (LauncherTarget){.target_found = target_found, .facing_angle = to_face};
} }
void on_entity_child_shape(cpBody *body, cpShape *shape, void *data); // declared here bc entity_destroy circular dependency void destroy_child_shape(cpBody *body, cpShape *shape, void *data)
// gs is for iterating over all child shapes and destroying those, too
static void destroy_body(GameState *gs, cpBody **body)
{ {
if (*body != NULL) GameState *gs = (GameState *)data;
if (cp_shape_entity(shape) == NULL)
{ {
cpBodyEachShape(*body, on_entity_child_shape, (void *)gs); // support the case where no parent entity *SPECIFICALLY* for grid_correct_for_holes,
cpSpaceRemoveBody(gs->space, *body); // where the entities that are part of the old grid are reused so entityids are preserved
cpBodyFree(*body); cpSpaceRemoveShape(gs->space, shape);
*body = NULL; cpShapeFree(shape);
}
else
{
entity_memory_free(gs, cp_shape_entity(shape));
} }
*body = NULL;
} }
// will destroy all shapes which are attached to the body in the entity // Destroys the entity and puts its slot back into the free list. Doesn't obey game rules
void entity_destroy(GameState *gs, Entity *e) // like making sure grids don't have holes in them, for that you want entity_destroy.
// *Does* free all owned memory/entities though, e.g grids free the boxes they own.
void entity_memory_free(GameState *gs, Entity *e)
{ {
flight_assert(e->exists); flight_assert(e->exists);
if (e->is_grid) if (e->is_grid)
{ {
BOXES_ITER(gs, cur, e) BOXES_ITER(gs, cur, e)
entity_destroy(gs, cur); {
entity_memory_free(gs, cur);
}
} }
if (e->is_box) if (e->is_box)
{ {
box_remove_from_boxes(gs, e); box_remove_from_boxes(gs, e);
} }
if (e->shape != NULL) if (e->shape != NULL)
{ {
cpSpaceRemoveShape(gs->space, e->shape); cpSpaceRemoveShape(gs->space, e->shape);
cpShapeFree(e->shape); cpShapeFree(e->shape);
e->shape = NULL; e->shape = NULL;
} }
destroy_body(gs, &e->body); if (e->body != 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); Entity *front_of_free_list = get_entity(gs, gs->free_list);
if (front_of_free_list != NULL) if (front_of_free_list != NULL)
flight_assert(!front_of_free_list->exists); flight_assert(!front_of_free_list->exists);
int gen = e->generation; unsigned int gen = e->generation;
*e = (Entity){0}; *e = (Entity){0};
e->generation = gen; e->generation = gen;
e->next_free_entity = gs->free_list; e->next_free_entity = gs->free_list;
gs->free_list = get_id(gs, e); gs->free_list = get_id(gs, e);
} }
void on_entity_child_shape(cpBody *body, cpShape *shape, void *data)
{
GameState *gs = (GameState *)data;
if (cp_shape_entity(shape) == NULL)
{
// support the case where no parent entity *SPECIFICALLY* for grid_correct_for_holes,
// where the entities that are part of the old grid are reused so entityids are preserved
cpSpaceRemoveShape(gs->space, shape);
cpShapeFree(shape);
}
else
{
entity_destroy(gs, cp_shape_entity(shape));
}
}
Entity *new_entity(GameState *gs) Entity *new_entity(GameState *gs)
{ {
Entity *to_return = NULL; Entity *to_return = NULL;
@ -828,7 +822,7 @@ static void grid_correct_for_holes(GameState *gs, struct Entity *grid)
int num_boxes = grid_num_boxes(gs, grid); int num_boxes = grid_num_boxes(gs, grid);
if (num_boxes == 0) if (num_boxes == 0)
{ {
entity_destroy(gs, grid); entity_memory_free(gs, grid);
return; return;
} }
if (num_boxes == 1) if (num_boxes == 1)
@ -966,15 +960,7 @@ static void grid_correct_for_holes(GameState *gs, struct Entity *grid)
} }
// destroys all the box shapes and the entities attached to those shapes // destroys all the box shapes and the entities attached to those shapes
entity_destroy(gs, grid); entity_memory_free(gs, grid);
}
static void grid_remove_box(GameState *gs, struct Entity *grid, struct Entity *box)
{
flight_assert(grid->is_grid);
flight_assert(box->is_box);
entity_destroy(gs, box);
grid_correct_for_holes(gs, grid);
} }
static void on_damage(cpArbiter *arb, cpSpace *space, cpDataPointer userData) static void on_damage(cpArbiter *arb, cpSpace *space, cpDataPointer userData)
@ -1055,7 +1041,7 @@ void destroy(GameState *gs)
{ {
if (gs->entities[i].exists) if (gs->entities[i].exists)
{ {
entity_destroy(gs, &gs->entities[i]); entity_memory_free(gs, &gs->entities[i]);
gs->entities[i] = (Entity){0}; gs->entities[i] = (Entity){0};
} }
} }
@ -1304,6 +1290,7 @@ enum GameVersion
{ {
VInitial, VInitial,
VNoGold, VNoGold,
VSafeSun,
VMax, // this minus one will be the version used VMax, // this minus one will be the version used
}; };
@ -1539,6 +1526,8 @@ SerMaybeFailure ser_entity(SerState *ser, GameState *gs, Entity *e)
SER_MAYBE_RETURN(ser_V2(ser, &e->sun_pos)); SER_MAYBE_RETURN(ser_V2(ser, &e->sun_pos));
SER_MAYBE_RETURN(ser_f(ser, &e->sun_mass)); SER_MAYBE_RETURN(ser_f(ser, &e->sun_mass));
SER_MAYBE_RETURN(ser_f(ser, &e->sun_radius)); SER_MAYBE_RETURN(ser_f(ser, &e->sun_radius));
if (ser->version >= VSafeSun)
SER_VAR(&e->sun_is_safe);
} }
SER_VAR(&e->is_grid); SER_VAR(&e->is_grid);
@ -2390,12 +2379,12 @@ void create_initial_world(GameState *gs)
{ {
const double mass_multiplier = 10.0; const double mass_multiplier = 10.0;
EntityID suns[] = { EntityID suns[] = {
create_sun(gs, new_entity(gs), ((cpVect){500.0, 0.0}), ((cpVect){0.0, 0.0}), 1000000.0 * mass_multiplier, 30.0), create_sun(gs, new_entity(gs), ((cpVect){500.0, 0.0}), ((cpVect){0.0, 0.0}), 1000000.0 * mass_multiplier, 70.0),
create_sun(gs, new_entity(gs), ((cpVect){500.0, 100.0}), ((cpVect){30.0, 0.0}), 10000.0 * mass_multiplier, 20.0),
create_sun(gs, new_entity(gs), ((cpVect){500.0, -100.0}), ((cpVect){-30.0, 0.0}), 10000.0 * mass_multiplier, 20.0),
create_sun(gs, new_entity(gs), ((cpVect){-7000.0, -50.0}), ((cpVect){0.0, 0.0}), 100000.0 * mass_multiplier, 20.0), create_sun(gs, new_entity(gs), ((cpVect){-7000.0, -50.0}), ((cpVect){0.0, 0.0}), 100000.0 * mass_multiplier, 20.0),
}; };
get_entity(gs, suns[0])->sun_is_safe = true;
for (int i = 0; i < ARRLEN(suns); i++) for (int i = 0; i < ARRLEN(suns); i++)
{ {
gs->suns[i] = suns[i]; gs->suns[i] = suns[i];
@ -2417,10 +2406,23 @@ void create_initial_world(GameState *gs)
create_bomb_station(gs, cpvadd(SUN_POS(0), cpv(0.0, 300.0)), BoxExplosive); create_bomb_station(gs, cpvadd(SUN_POS(0), cpv(0.0, 300.0)), BoxExplosive);
create_bomb_station(gs, cpvadd(SUN_POS(0), cpv(0.0, -300.0)), BoxCloaking); create_bomb_station(gs, cpvadd(SUN_POS(0), cpv(0.0, -300.0)), BoxCloaking);
create_bomb_station(gs, cpvadd(SUN_POS(0), cpv(300.0, 0.0)), BoxMissileLauncher); create_bomb_station(gs, cpvadd(SUN_POS(0), cpv(300.0, 0.0)), BoxMissileLauncher);
create_bomb_station(gs, cpvadd(SUN_POS(3), cpv(0.0, 300.0)), BoxMerge); create_bomb_station(gs, cpvadd(SUN_POS(1), cpv(0.0, 300.0)), BoxMerge);
#undef SUN_POS #undef SUN_POS
#else #else
#if 1 // basic test
{
bool indestructible = false;
enum CompassRotation rot = Right;
Entity *grid = new_entity(gs);
grid_create(gs, grid);
entity_set_pos(grid, cpv(-1.5, 0.0));
BOX_AT_TYPE(grid, cpv(0.0, 0.0), BoxHullpiece);
BOX_AT_TYPE(grid, cpv(BOX_SIZE, 0.0), BoxHullpiece);
entity_ensure_in_orbit(gs, grid);
}
#endif
#if 1 // present the stations #if 1 // present the stations
Log("Creating debug world\n"); Log("Creating debug world\n");
@ -2551,6 +2553,8 @@ void process(struct GameState *gs, double dt)
} }
} }
#ifndef NO_GRAVITY #ifndef NO_GRAVITY
if (!from_sun->sun_is_safe)
{
from_sun->sun_vel = cpvadd(from_sun->sun_vel, cpvmult(accel, dt)); from_sun->sun_vel = cpvadd(from_sun->sun_vel, cpvmult(accel, dt));
from_sun->sun_pos = cpvadd(from_sun->sun_pos, cpvmult(from_sun->sun_vel, dt)); from_sun->sun_pos = cpvadd(from_sun->sun_pos, cpvmult(from_sun->sun_vel, dt));
@ -2559,6 +2563,7 @@ void process(struct GameState *gs, double dt)
from_sun->sun_vel = cpvmult(from_sun->sun_vel, -0.8); from_sun->sun_vel = cpvmult(from_sun->sun_vel, -0.8);
from_sun->sun_pos = cpvmult(cpvnormalize(from_sun->sun_pos), INSTANT_DEATH_DISTANCE_FROM_CENTER); from_sun->sun_pos = cpvmult(cpvnormalize(from_sun->sun_pos), INSTANT_DEATH_DISTANCE_FROM_CENTER);
} }
}
#endif #endif
} }
} }
@ -2800,9 +2805,8 @@ void process(struct GameState *gs, double dt)
Entity *cur_box = cp_shape_entity(maybe_box_to_destroy); Entity *cur_box = cp_shape_entity(maybe_box_to_destroy);
if (!cur_box->indestructible && !cur_box->is_platonic) if (!cur_box->indestructible && !cur_box->is_platonic)
{ {
Entity *cur_grid = cp_body_entity(cpShapeGetBody(maybe_box_to_destroy));
p->damage -= DAMAGE_TO_PLAYER_PER_BLOCK * ((BATTERY_CAPACITY - cur_box->energy_used) / BATTERY_CAPACITY); p->damage -= DAMAGE_TO_PLAYER_PER_BLOCK * ((BATTERY_CAPACITY - cur_box->energy_used) / BATTERY_CAPACITY);
grid_remove_box(gs, cur_grid, cur_box); cur_box->flag_for_destruction = true;
} }
} }
else if (box_unlocked(player, player->input.build_type)) else if (box_unlocked(player, player->input.build_type))
@ -2840,7 +2844,7 @@ void process(struct GameState *gs, double dt)
#endif #endif
if (p->damage >= 1.0) if (p->damage >= 1.0)
{ {
entity_destroy(gs, p); p->flag_for_destruction = true;
player->entity = (EntityID){0}; player->entity = (EntityID){0};
} }
@ -2850,12 +2854,8 @@ void process(struct GameState *gs, double dt)
PROFILE_SCOPE("process entities") PROFILE_SCOPE("process entities")
{ {
for (size_t i = 0; i < gs->cur_next_entity; i++) ENTITIES_ITER(gs, e)
{ {
Entity *e = &gs->entities[i];
if (!e->exists)
continue;
if (e->body != NULL && cpvlengthsq((entity_pos(e))) > (INSTANT_DEATH_DISTANCE_FROM_CENTER * INSTANT_DEATH_DISTANCE_FROM_CENTER)) if (e->body != NULL && cpvlengthsq((entity_pos(e))) > (INSTANT_DEATH_DISTANCE_FROM_CENTER * INSTANT_DEATH_DISTANCE_FROM_CENTER))
{ {
#ifdef INTENSIVE_PROFILING #ifdef INTENSIVE_PROFILING
@ -2883,10 +2883,8 @@ void process(struct GameState *gs, double dt)
} }
else else
{ {
entity_destroy(gs, e); e->flag_for_destruction = true;
continue;
} }
continue;
} }
} }
@ -2899,13 +2897,24 @@ void process(struct GameState *gs, double dt)
cpVect pos_rel_sun = (cpvsub(entity_pos(e), (entity_pos(i.sun)))); cpVect pos_rel_sun = (cpvsub(entity_pos(e), (entity_pos(i.sun))));
cpFloat sqdist = cpvlengthsq(pos_rel_sun); cpFloat sqdist = cpvlengthsq(pos_rel_sun);
bool is_entity_dangerous = false;
is_entity_dangerous |= e->is_missile;
if (e->is_box)
{
is_entity_dangerous |= e->box_type == BoxExplosive;
}
if (is_entity_dangerous && sqdist < sun_dist_no_gravity(i.sun) * sun_dist_no_gravity(i.sun))
{
e->flag_for_destruction = true;
break;
}
if (!e->is_grid) // grids aren't damaged (this edge case sucks!) if (!e->is_grid) // grids aren't damaged (this edge case sucks!)
{ {
#ifdef INTENSIVE_PROFILING #ifdef INTENSIVE_PROFILING
PROFILE_SCOPE("Grid processing") PROFILE_SCOPE("Grid processing")
#endif #endif
{ {
sqdist = cpvlengthsq(cpvsub((entity_pos(e)), (entity_pos(i.sun))));
if (sqdist < (i.sun->sun_radius * i.sun->sun_radius)) if (sqdist < (i.sun->sun_radius * i.sun->sun_radius))
{ {
e->damage += 10.0 * dt; e->damage += 10.0 * dt;
@ -2938,8 +2947,7 @@ void process(struct GameState *gs, double dt)
do_explosion(gs, e, dt); do_explosion(gs, e, dt);
if (e->explosion_progress >= EXPLOSION_TIME) if (e->explosion_progress >= EXPLOSION_TIME)
{ {
entity_destroy(gs, e); e->flag_for_destruction = true;
continue;
} }
} }
} }
@ -2987,7 +2995,7 @@ void process(struct GameState *gs, double dt)
explosion->explosion_vel = cpBodyGetVelocity(e->body); explosion->explosion_vel = cpBodyGetVelocity(e->body);
explosion->explosion_push_strength = MISSILE_EXPLOSION_PUSH; explosion->explosion_push_strength = MISSILE_EXPLOSION_PUSH;
explosion->explosion_radius = MISSILE_EXPLOSION_RADIUS; explosion->explosion_radius = MISSILE_EXPLOSION_RADIUS;
entity_destroy(gs, e); e->flag_for_destruction = true;
continue; continue;
} }
} }
@ -2999,11 +3007,6 @@ void process(struct GameState *gs, double dt)
PROFILE_SCOPE("Box processing") PROFILE_SCOPE("Box processing")
#endif #endif
{ {
if (e->is_platonic)
{
e->damage = 0.0;
gs->platonic_positions[(int)e->box_type] = entity_pos(e);
}
if (e->box_type == BoxExplosive && e->damage >= EXPLOSION_DAMAGE_THRESHOLD) if (e->box_type == BoxExplosive && e->damage >= EXPLOSION_DAMAGE_THRESHOLD)
{ {
Entity *explosion = new_entity(gs); Entity *explosion = new_entity(gs);
@ -3013,7 +3016,12 @@ void process(struct GameState *gs, double dt)
explosion->explosion_push_strength = BOMB_EXPLOSION_PUSH; explosion->explosion_push_strength = BOMB_EXPLOSION_PUSH;
explosion->explosion_radius = BOMB_EXPLOSION_RADIUS; explosion->explosion_radius = BOMB_EXPLOSION_RADIUS;
if (!e->is_platonic) if (!e->is_platonic)
grid_remove_box(gs, get_entity(gs, e->shape_parent_entity), e); e->flag_for_destruction = true;
}
if (e->is_platonic)
{
e->damage = 0.0;
gs->platonic_positions[(int)e->box_type] = entity_pos(e);
} }
if (e->box_type == BoxMerge) if (e->box_type == BoxMerge)
{ {
@ -3091,7 +3099,7 @@ void process(struct GameState *gs, double dt)
flight_assert(box_grid(cur) == box_grid(from_merge)); flight_assert(box_grid(cur) == box_grid(from_merge));
cur = next; cur = next;
} }
entity_destroy(gs, other_grid); other_grid->flag_for_destruction = true;
} }
} }
} }
@ -3099,7 +3107,7 @@ void process(struct GameState *gs, double dt)
} }
if (e->damage >= 1.0) if (e->damage >= 1.0)
{ {
grid_remove_box(gs, get_entity(gs, e->shape_parent_entity), e); e->flag_for_destruction = true;
} }
} }
} }
@ -3160,7 +3168,7 @@ void process(struct GameState *gs, double dt)
rect_query(gs->space, (BoxCentered){ rect_query(gs->space, (BoxCentered){
.pos = cpvadd(entity_pos(cur_box), cpvmult(box_facing_vector(cur_box), BOX_SIZE)), .pos = cpvadd(entity_pos(cur_box), cpvmult(box_facing_vector(cur_box), BOX_SIZE)),
.rotation = box_rotation(cur_box), .rotation = box_rotation(cur_box),
.size = cpv(BOX_SIZE/2.0 - 0.03, BOX_SIZE/2.0 - 0.03), .size = cpv(BOX_SIZE / 2.0 - 0.03, BOX_SIZE / 2.0 - 0.03),
}); });
QUEUE_ITER(&query_result, QueryResult, res) QUEUE_ITER(&query_result, QueryResult, res)
{ {
@ -3397,6 +3405,22 @@ void process(struct GameState *gs, double dt)
} }
} }
PROFILE_SCOPE("Delete entities")
{
ENTITIES_ITER(gs, e)
{
if (e->flag_for_destruction)
{
Entity *grid = NULL;
if (e->is_box)
grid = box_grid(e);
entity_memory_free(gs, e);
if (grid != NULL)
grid_correct_for_holes(gs, grid);
}
}
}
PROFILE_SCOPE("chipmunk physics processing") PROFILE_SCOPE("chipmunk physics processing")
{ {
cpSpaceStep(gs->space, dt); cpSpaceStep(gs->space, dt);

@ -233,10 +233,6 @@ static struct BoxInfo
.image_path = "loaded/merge.png", .image_path = "loaded/merge.png",
}, },
}; };
#define ENTITIES_ITER(cur) \
for (Entity *cur = gs.entities; cur < gs.entities + gs.cur_next_entity; \
cur++) \
if (cur->exists)
// suppress compiler warning about ^^ above used in floating point context // suppress compiler warning about ^^ above used in floating point context
#define ARRLENF(arr) ((float)sizeof(arr) / sizeof(*arr)) #define ARRLENF(arr) ((float)sizeof(arr) / sizeof(*arr))
static struct SquadMeta static struct SquadMeta
@ -299,7 +295,7 @@ static void new_particle(cpVect pos, cpVect vel)
} }
if (!created) if (!created)
{ {
Log("TOO MANY PARTICLES"); Log("TOO MANY PARTICLES\n");
} }
} }
@ -472,6 +468,11 @@ void recalculate_camera_pos()
{ \ { \
.r = 0.0f, .g = 0.0f, .b = 1.0f, .a = 1.0f \ .r = 0.0f, .g = 0.0f, .b = 1.0f, .a = 1.0f \
} }
#define GREEN \
(Color) \
{ \
.r = 0.0f, .g = 1.0f, .b = 0.0f, .a = 1.0f \
}
#define GOLD colhex(255, 215, 0) #define GOLD colhex(255, 215, 0)
typedef struct Color typedef struct Color
@ -957,7 +958,7 @@ cpVect pointV2(sgp_point p)
static void draw_circle(cpVect point, double radius) static void draw_circle(cpVect point, double radius)
{ {
#define POINTS 64 #define POINTS 128
sgp_line lines[POINTS]; sgp_line lines[POINTS];
for (int i = 0; i < POINTS; i++) for (int i = 0; i < POINTS; i++)
{ {
@ -2049,7 +2050,7 @@ static void frame(void)
{ {
if (p->alive) if (p->alive)
{ {
p->alive_for += dt*1.5; p->alive_for += dt * 1.5;
p->pos = cpvadd(p->pos, cpvmult(p->vel, dt)); p->pos = cpvadd(p->pos, cpvmult(p->vel, dt));
if (p->alive_for > 1.0) if (p->alive_for > 1.0)
{ {
@ -2332,7 +2333,7 @@ static void frame(void)
hovering_this_player = (EntityID){0}; hovering_this_player = (EntityID){0};
// draw all types of entities // draw all types of entities
ENTITIES_ITER(e) ENTITIES_ITER(&gs, e)
{ {
// draw grid // draw grid
if (e->is_grid) if (e->is_grid)
@ -2734,7 +2735,9 @@ static void frame(void)
// can draw at 0,0 because everything relative to sun now! // can draw at 0,0 because everything relative to sun now!
// sun DEATH RADIUS // sun DEATH RADIUS
if (i.sun->sun_is_safe)
set_color(GREEN);
else
set_color(BLUE); set_color(BLUE);
draw_circle((cpVect){0}, sun_dist_no_gravity(i.sun)); draw_circle((cpVect){0}, sun_dist_no_gravity(i.sun));
} }

@ -282,7 +282,7 @@ void server(void *info_raw)
Entity *player_body = get_entity(&gs, gs.players[player_index].entity); Entity *player_body = get_entity(&gs, gs.players[player_index].entity);
if (player_body != NULL) if (player_body != NULL)
{ {
entity_destroy(&gs, player_body); entity_memory_free(&gs, player_body);
} }
opus_encoder_destroy(player_encoders[player_index]); opus_encoder_destroy(player_encoders[player_index]);
player_encoders[player_index] = NULL; player_encoders[player_index] = NULL;

@ -130,7 +130,8 @@
#include "cpVect.h" // offers vector functions and types for the structs #include "cpVect.h" // offers vector functions and types for the structs
#include "miniaudio.h" // @Robust BAD. using miniaudio mutex construct for server thread synchronization. AWFUL! #include "miniaudio.h" // @Robust BAD. using miniaudio mutex construct for server thread synchronization. AWFUL!
#include <math.h> // sqrt and cos vector functions #define _USE_MATH_DEFINES
#include <math.h> // sqrt and cos vector functions and PI
#include <stdint.h> // tick is unsigned integer #include <stdint.h> // tick is unsigned integer
#include <stdio.h> // logging on errors for functions #include <stdio.h> // logging on errors for functions
@ -263,6 +264,7 @@ typedef struct PlatonicDetection
typedef struct Entity typedef struct Entity
{ {
bool exists; bool exists;
bool flag_for_destruction;
EntityID next_free_entity; EntityID next_free_entity;
unsigned int generation; unsigned int generation;
bool always_visible; // always serialized to the player. bool always_visible; // always serialized to the player.
@ -306,6 +308,7 @@ typedef struct Entity
cpVect sun_pos; cpVect sun_pos;
double sun_mass; double sun_mass;
double sun_radius; double sun_radius;
bool sun_is_safe;
// missile // missile
bool is_missile; bool is_missile;
@ -397,6 +400,10 @@ typedef struct SunIter
for (SunIter i = {0}; i.i < MAX_SUNS; i.i++) \ for (SunIter i = {0}; i.i < MAX_SUNS; i.i++) \
if ((i.sun = get_entity(gs_ptr, (gs_ptr)->suns[i.i])) != NULL) if ((i.sun = get_entity(gs_ptr, (gs_ptr)->suns[i.i])) != NULL)
#define ENTITIES_ITER(gs, cur) \
for (Entity *cur = (gs)->entities; cur < (gs)->entities + (gs)->cur_next_entity; cur++) \
if (cur->exists)
// gotta update the serialization functions when this changes // gotta update the serialization functions when this changes
typedef struct GameState typedef struct GameState
{ {
@ -413,7 +420,7 @@ typedef struct GameState
bool server_side_computing; // some things only the server should know and calculate, like platonic locations bool server_side_computing; // some things only the server should know and calculate, like platonic locations
// Entity arena // Entity arena
// ent:ity pointers can't move around because of how the physics engine handles user data. // entity 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 // if you really need this, potentially refactor to store entity IDs instead of pointers
// in the shapes and bodies of chipmunk. Would require editing the library I think // in the shapes and bodies of chipmunk. Would require editing the library I think
Entity *entities; Entity *entities;
@ -426,8 +433,8 @@ typedef struct GameState
for (Player *cur = players; cur < players + MAX_PLAYERS; cur++) \ for (Player *cur = players; cur < players + MAX_PLAYERS; cur++) \
if (cur->connected) if (cur->connected)
#define PI 3.14159f #define PI M_PI
#define TAU (PI * 2.0f) #define TAU (M_PI * 2.0)
// returns in radians // returns in radians
static inline double rotangle(enum CompassRotation rot) static inline double rotangle(enum CompassRotation rot)
@ -539,7 +546,7 @@ bool could_learn_from_scanner(Player *for_player, Entity *box);
void entity_set_pos(Entity *e, cpVect pos); void entity_set_pos(Entity *e, cpVect pos);
double entity_rotation(Entity *e); double entity_rotation(Entity *e);
void entity_ensure_in_orbit(GameState *gs, Entity *e); void entity_ensure_in_orbit(GameState *gs, Entity *e);
void entity_destroy(GameState *gs, Entity *e); void entity_memory_free(GameState *gs, Entity *e);
#define BOX_CHAIN_ITER(gs, cur, starting_box) for (Entity *cur = get_entity(gs, starting_box); cur != NULL; cur = get_entity(gs, cur->next_box)) #define BOX_CHAIN_ITER(gs, cur, starting_box) for (Entity *cur = get_entity(gs, starting_box); cur != NULL; cur = get_entity(gs, cur->next_box))
#define BOXES_ITER(gs, cur, grid_entity_ptr) BOX_CHAIN_ITER(gs, cur, (grid_entity_ptr)->boxes) #define BOXES_ITER(gs, cur, grid_entity_ptr) BOX_CHAIN_ITER(gs, cur, (grid_entity_ptr)->boxes)
typedef struct LauncherTarget typedef struct LauncherTarget
@ -705,5 +712,5 @@ static inline double deg2rad(double deg)
return (deg / 360.0f) * 2.0f * PI; return (deg / 360.0f) * 2.0f * PI;
} }
#define min(X,Y) (((X) < (Y)) ? (X) : (Y)) #define min(X, Y) (((X) < (Y)) ? (X) : (Y))
#define max(X,Y) (((X) > (Y)) ? (X) : (Y)) #define max(X, Y) (((X) > (Y)) ? (X) : (Y))
Loading…
Cancel
Save