collision grid + perf improvements
parent
e43b167435
commit
3fba1bc1d4
|
@ -3,7 +3,7 @@
|
|||
|
||||
static debug_draw_queue draw_queue = {0};
|
||||
|
||||
#if !defined(_DEBUG) || 1
|
||||
#if !defined(_DEBUG) || 0
|
||||
static bool draw_is_enabled = false;
|
||||
#else
|
||||
static bool draw_is_enabled = true;
|
||||
|
|
|
@ -19,10 +19,12 @@ uint64_t entity_spawn(uint16_t class_id) {
|
|||
|
||||
if (class_id != EKIND_SERVER) {
|
||||
librg_entity_track(world_tracker(), e);
|
||||
librg_entity_track(world_collision_grid(), e);
|
||||
ecs_set(world_ecs(), e, Velocity, { 0 });
|
||||
entity_set_position(e, (float)(rand() % world_dim()), (float)(rand() % world_dim()));
|
||||
|
||||
librg_entity_owner_set(world_tracker(), e, (int64_t)e);
|
||||
librg_entity_owner_set(world_collision_grid(), e, (int64_t)e);
|
||||
}
|
||||
|
||||
return (uint64_t)e;
|
||||
|
@ -59,6 +61,7 @@ bool entity_spawn_provided(uint16_t id) {
|
|||
|
||||
void entity_batch_despawn(uint64_t *ids, size_t num_ids) {
|
||||
for (size_t i = 0; i < num_ids; i++ ) {
|
||||
librg_entity_untrack(world_collision_grid(), ids[i]);
|
||||
librg_entity_untrack(world_tracker(), ids[i]);
|
||||
ecs_delete(world_ecs(), ids[i]);
|
||||
}
|
||||
|
@ -66,6 +69,7 @@ void entity_batch_despawn(uint64_t *ids, size_t num_ids) {
|
|||
|
||||
void entity_despawn(uint64_t ent_id) {
|
||||
librg_entity_untrack(world_tracker(), ent_id);
|
||||
librg_entity_untrack(world_collision_grid(), ent_id);
|
||||
ecs_delete(world_ecs(), ent_id);
|
||||
}
|
||||
|
||||
|
@ -75,6 +79,7 @@ void entity_set_position(uint64_t ent_id, float x, float y) {
|
|||
p->x = x;
|
||||
p->y = y;
|
||||
librg_entity_chunk_set(world_tracker(), ent_id, librg_chunk_from_realpos(world_tracker(), x, y, 0));
|
||||
librg_entity_chunk_set(world_collision_grid(), ent_id, librg_chunk_from_realpos(world_collision_grid(), x, y, 0));
|
||||
entity_wake(ent_id);
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,8 @@ void BlockCollisions(ecs_iter_t *it) {
|
|||
}
|
||||
}
|
||||
|
||||
#define MAX_PHYSBODY_CHECKS 512
|
||||
|
||||
void BodyCollisions(ecs_iter_t *it) {
|
||||
Position *p = ecs_field(it, Position, 1);
|
||||
Velocity *v = ecs_field(it, Velocity, 2);
|
||||
|
@ -154,85 +156,90 @@ void BodyCollisions(ecs_iter_t *it) {
|
|||
}
|
||||
#endif
|
||||
|
||||
ecs_iter_t it2 = ecs_query_iter(it->world, ecs_rigidbodies);
|
||||
size_t ents_count = MAX_PHYSBODY_CHECKS;
|
||||
static int64_t ents[MAX_PHYSBODY_CHECKS] = {0};
|
||||
librg_chunk chk = librg_entity_chunk_get(world_collision_grid(), it->entities[i]);
|
||||
librg_world_fetch_chunk(world_collision_grid(), chk, ents, &ents_count);
|
||||
|
||||
while (ecs_query_next(&it2)) {
|
||||
for (int j = 0; j < it2.count; j++) {
|
||||
if (it->entities[i] == it2.entities[j]) continue;
|
||||
for (size_t j = 0; j < ents_count; j++) {
|
||||
uint64_t ent_id = (uint64_t)ents[j];
|
||||
if (it->entities[i] == ent_id) continue;
|
||||
if (!ecs_get(it->world, ent_id, PhysicsBody)) continue;
|
||||
if ( ecs_get(it->world, ent_id, TriggerOnly)) continue;
|
||||
if ( ecs_get(it->world, ent_id, IsInVehicle)) continue;
|
||||
|
||||
Position *p2 = ecs_field(&it2, Position, 1);
|
||||
Velocity *v2 = ecs_field(&it2, Velocity, 2);
|
||||
PhysicsBody *b2 = ecs_field(&it2, PhysicsBody, 3);
|
||||
Position *p2 = ecs_get_mut(it->world, ent_id, Position);
|
||||
Velocity *v2 = ecs_get_mut(it->world, ent_id, Velocity);
|
||||
PhysicsBody *b2 = ecs_get_mut(it->world, ent_id, PhysicsBody);
|
||||
|
||||
float p_x = p[i].x;
|
||||
float p_y = p[i].y;
|
||||
float p2_x = p2[j].x /*+ v2[j].x*/;
|
||||
float p2_y = p2[j].y /*+ v2[j].y*/;
|
||||
float p_x = p[i].x;
|
||||
float p_y = p[i].y;
|
||||
float p2_x = p2->x /*+ v2->x*/;
|
||||
float p2_y = p2->y /*+ v2->y*/;
|
||||
|
||||
c2AABB box_a = {
|
||||
.min = { p_x - WORLD_BLOCK_SIZE / 2, p_y - WORLD_BLOCK_SIZE / 4 },
|
||||
.max = { p_x + WORLD_BLOCK_SIZE / 2, p_y + WORLD_BLOCK_SIZE / 4 },
|
||||
};
|
||||
c2AABB box_a = {
|
||||
.min = { p_x - WORLD_BLOCK_SIZE / 2, p_y - WORLD_BLOCK_SIZE / 4 },
|
||||
.max = { p_x + WORLD_BLOCK_SIZE / 2, p_y + WORLD_BLOCK_SIZE / 4 },
|
||||
};
|
||||
|
||||
c2AABB box_b = {
|
||||
.min = { p2_x - WORLD_BLOCK_SIZE / 2, p2_y - WORLD_BLOCK_SIZE / 4 },
|
||||
.max = { p2_x + WORLD_BLOCK_SIZE / 2, p2_y + WORLD_BLOCK_SIZE / 4 },
|
||||
};
|
||||
c2AABB box_b = {
|
||||
.min = { p2_x - WORLD_BLOCK_SIZE / 2, p2_y - WORLD_BLOCK_SIZE / 4 },
|
||||
.max = { p2_x + WORLD_BLOCK_SIZE / 2, p2_y + WORLD_BLOCK_SIZE / 4 },
|
||||
};
|
||||
|
||||
// do a basic sweep first
|
||||
float r1x = (box_a.max.x-box_a.min.x);
|
||||
float r1y = (box_a.max.y-box_a.min.y);
|
||||
float r1 = (r1x*r1x + r1y*r1y)*.5f;
|
||||
// do a basic sweep first
|
||||
float r1x = (box_a.max.x-box_a.min.x);
|
||||
float r1y = (box_a.max.y-box_a.min.y);
|
||||
float r1 = (r1x*r1x + r1y*r1y)*.5f;
|
||||
|
||||
float r2x = (box_b.max.x-box_b.min.x);
|
||||
float r2y = (box_b.max.y-box_b.min.y);
|
||||
float r2 = (r2x*r2x + r2y*r2y)*.5f;
|
||||
float r2x = (box_b.max.x-box_b.min.x);
|
||||
float r2y = (box_b.max.y-box_b.min.y);
|
||||
float r2 = (r2x*r2x + r2y*r2y)*.5f;
|
||||
|
||||
{
|
||||
float dx = (p2_x-p_x);
|
||||
float dy = (p2_y-p_y);
|
||||
float d = (dx*dx + dy*dy);
|
||||
{
|
||||
float dx = (p2_x-p_x);
|
||||
float dy = (p2_y-p_y);
|
||||
float d = (dx*dx + dy*dy);
|
||||
|
||||
if (d > r1 && d > r2)
|
||||
continue;
|
||||
}
|
||||
if (d > r1 && d > r2)
|
||||
continue;
|
||||
}
|
||||
|
||||
c2Circle circle_a = {
|
||||
.p = { p_x, p_y },
|
||||
.r = r1/2.f,
|
||||
};
|
||||
c2Circle circle_a = {
|
||||
.p = { p_x, p_y },
|
||||
.r = r1/2.f,
|
||||
};
|
||||
|
||||
c2Circle circle_b = {
|
||||
.p = { p2_x, p2_y },
|
||||
.r = r2/2.f,
|
||||
};
|
||||
c2Circle circle_b = {
|
||||
.p = { p2_x, p2_y },
|
||||
.r = r2/2.f,
|
||||
};
|
||||
|
||||
const void *shapes_a[] = { &circle_a, &box_a };
|
||||
const void *shapes_b[] = { &circle_b, &box_b };
|
||||
const void *shapes_a[] = { &circle_a, &box_a };
|
||||
const void *shapes_b[] = { &circle_b, &box_b };
|
||||
|
||||
c2Manifold m = { 0 };
|
||||
c2Collide(shapes_a[b[i].kind], 0, b[i].kind, shapes_b[b2[j].kind], 0, b2[j].kind, &m);
|
||||
c2Manifold m = { 0 };
|
||||
c2Collide(shapes_a[b[i].kind], 0, b[i].kind, shapes_b[b2->kind], 0, b2->kind, &m);
|
||||
|
||||
c2v n = m.n;
|
||||
c2v n = m.n;
|
||||
|
||||
for (int k = 0; k < m.count; k++) {
|
||||
float d = m.depths[k];
|
||||
for (int k = 0; k < m.count; k++) {
|
||||
float d = m.depths[k];
|
||||
#if 0
|
||||
{
|
||||
c2v pos = m.contact_points[k];
|
||||
debug_v2 a = { pos.x, pos.y };
|
||||
debug_v2 b = { pos.x + n.x*d, pos.y + n.y*d };
|
||||
debug_push_line(a, b, 0xF77FFFFF);
|
||||
}
|
||||
{
|
||||
c2v pos = m.contact_points[k];
|
||||
debug_v2 a = { pos.x, pos.y };
|
||||
debug_v2 b = { pos.x + n.x*d, pos.y + n.y*d };
|
||||
debug_push_line(a, b, 0xF77FFFFF);
|
||||
}
|
||||
#endif
|
||||
|
||||
float m1 = b2[j].mass == INFINITE_MASS ? b[i].mass : b2[j].mass;
|
||||
float m2 = b[i].mass == INFINITE_MASS ? (ZPL_F32_MAX-1.0f) : b[i].mass;
|
||||
float mass_ratio = m1 / m2;
|
||||
float m1 = b2->mass == INFINITE_MASS ? b[i].mass : b2->mass;
|
||||
float m2 = b[i].mass == INFINITE_MASS ? (ZPL_F32_MAX-1.0f) : b[i].mass;
|
||||
float mass_ratio = m1 / m2;
|
||||
|
||||
v[i].x -= n.x*d*mass_ratio;
|
||||
v[i].y -= n.y*d*mass_ratio;
|
||||
}
|
||||
v[i].x -= n.x*d*mass_ratio;
|
||||
v[i].y -= n.y*d*mass_ratio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,6 +264,7 @@ void IntegratePositions(ecs_iter_t *it) {
|
|||
p[i].y += v[i].y*safe_dt_val;
|
||||
|
||||
librg_entity_chunk_set(world_tracker(), it->entities[i], librg_chunk_from_realpos(world_tracker(), p[i].x, p[i].y, 0));
|
||||
librg_entity_chunk_set(world_collision_grid(), it->entities[i], librg_chunk_from_realpos(world_collision_grid(), p[i].x, p[i].y, 0));
|
||||
|
||||
s[i].tick_delay = 0.0f;
|
||||
s[i].last_update = 0.0f;
|
||||
|
|
|
@ -292,6 +292,7 @@ void world_chunk_setup_grid(void) {
|
|||
static inline
|
||||
void world_configure_tracker(void) {
|
||||
world.tracker = librg_world_create();
|
||||
world.collision_grid = librg_world_create();
|
||||
|
||||
ZPL_ASSERT_MSG(world.tracker, "[ERROR] An error occurred while trying to create a server world.");
|
||||
|
||||
|
@ -303,6 +304,13 @@ void world_configure_tracker(void) {
|
|||
librg_event_set(world.tracker, LIBRG_WRITE_CREATE, tracker_write_create);
|
||||
librg_event_set(world.tracker, LIBRG_WRITE_REMOVE, tracker_write_remove);
|
||||
librg_event_set(world.tracker, LIBRG_WRITE_UPDATE, tracker_write_update);
|
||||
|
||||
/* config our collision grid */
|
||||
uint16_t chks = world.chunk_size / 2;
|
||||
uint16_t chkm = world.chunk_amount * 2;
|
||||
librg_config_chunksize_set(world.collision_grid, WORLD_BLOCK_SIZE * chks, WORLD_BLOCK_SIZE * chks, 1);
|
||||
librg_config_chunkamount_set(world.collision_grid, chkm, chkm, 0);
|
||||
librg_config_chunkoffset_set(world.collision_grid, LIBRG_OFFSET_BEG, LIBRG_OFFSET_BEG, LIBRG_OFFSET_BEG);
|
||||
}
|
||||
|
||||
static inline
|
||||
|
@ -379,6 +387,7 @@ int32_t world_init(int32_t seed, uint16_t chunk_size, uint16_t chunk_amount) {
|
|||
}
|
||||
|
||||
int32_t world_destroy(void) {
|
||||
librg_world_destroy(world.collision_grid);
|
||||
librg_world_destroy(world.tracker);
|
||||
ecs_fini(world.ecs);
|
||||
zpl_mfree(world.chunk_mapping);
|
||||
|
@ -548,6 +557,10 @@ librg_world* world_tracker() {
|
|||
return world.tracker;
|
||||
}
|
||||
|
||||
librg_world* world_collision_grid() {
|
||||
return world.collision_grid;
|
||||
}
|
||||
|
||||
void world_pause(void) {
|
||||
ecs_set_time_scale(world.ecs, 0.0f);
|
||||
world.is_paused = true;
|
||||
|
|
|
@ -56,7 +56,7 @@ typedef struct {
|
|||
ecs_query_t *ecs_clientinfo;
|
||||
ecs_query_t *ecs_layeroverriden;
|
||||
ecs_entity_t *chunk_mapping;
|
||||
librg_world *tracker;
|
||||
librg_world *tracker, *collision_grid;
|
||||
world_pkt_reader_proc *reader_proc;
|
||||
world_pkt_writer_proc *writer_proc;
|
||||
} world_data;
|
||||
|
@ -77,6 +77,7 @@ ecs_query_t *world_ecs_alive_player(void);
|
|||
ecs_query_t *world_ecs_clientinfo(void);
|
||||
void world_set_stage(ecs_world_t *ecs);
|
||||
librg_world *world_tracker(void);
|
||||
librg_world *world_collision_grid(void);
|
||||
|
||||
// NOTE(zaklaus): World simulation time control
|
||||
void world_pause(void);
|
||||
|
|
|
@ -49,6 +49,7 @@ int main(int argc, char** argv) {
|
|||
zpl_opts_add(&opts, "p", "preview-map", "draw world preview", ZPL_OPTS_FLAG);
|
||||
zpl_opts_add(&opts, "s", "seed", "world seed", ZPL_OPTS_INT);
|
||||
zpl_opts_add(&opts, "r", "random-seed", "generate random world seed", ZPL_OPTS_FLAG);
|
||||
zpl_opts_add(&opts, "ed", "enable-dash", "enables flecs dash", ZPL_OPTS_FLAG);
|
||||
//zpl_opts_add(&opts, "cs", "chunk-size", "amount of blocks within a chunk (single axis)", ZPL_OPTS_INT);
|
||||
zpl_opts_add(&opts, "ws", "world-size", "amount of chunks within a world (single axis)", ZPL_OPTS_INT);
|
||||
zpl_opts_add(&opts, "ip", "host", "host IP address", ZPL_OPTS_STRING);
|
||||
|
@ -64,6 +65,7 @@ int main(int argc, char** argv) {
|
|||
|
||||
int8_t is_viewer_only = zpl_opts_has_arg(&opts, "viewer-only");
|
||||
int8_t is_server_only = zpl_opts_has_arg(&opts, "server-only");
|
||||
int8_t is_dash_enabled = zpl_opts_has_arg(&opts, "enable-dash");
|
||||
int32_t seed = (int32_t)zpl_opts_integer(&opts, "seed", DEFAULT_WORLD_SEED);
|
||||
uint16_t world_size = (uint16_t)zpl_opts_integer(&opts, "world-size", DEFAULT_WORLD_SIZE);
|
||||
uint16_t chunk_size = DEFAULT_CHUNK_SIZE; //zpl_opts_integer(&opts, "chunk-size", DEFAULT_CHUNK_SIZE);
|
||||
|
@ -88,7 +90,7 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
sighandler_register();
|
||||
game_init(host, port, play_mode, 1, seed, chunk_size, world_size, 0);
|
||||
game_init(host, port, play_mode, 1, seed, chunk_size, world_size, is_dash_enabled);
|
||||
game_setup_ecs();
|
||||
game_run();
|
||||
|
||||
|
|
|
@ -90,6 +90,9 @@ void platform_input() {
|
|||
}
|
||||
}
|
||||
|
||||
void recalc_max_mobs();
|
||||
extern uint64_t mob_kills;
|
||||
|
||||
void platform_render() {
|
||||
platform_resize_window();
|
||||
|
||||
|
@ -117,8 +120,26 @@ void platform_render() {
|
|||
nk_end(game_ui);
|
||||
}
|
||||
|
||||
|
||||
notification_draw();
|
||||
|
||||
if (nk_begin(game_ui, "Debug stuff", nk_rect(400, 10, 220, 140),
|
||||
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|NK_WINDOW_TITLE))
|
||||
{
|
||||
nk_layout_row_dynamic(game_ui, 0, 1);
|
||||
if (nk_button_label(game_ui, "max_mobs hack")) {
|
||||
mob_kills = 2000;
|
||||
recalc_max_mobs();
|
||||
}
|
||||
if (nk_button_label(game_ui, "big hp")) {
|
||||
ecs_entity_t plr = camera_get().ent_id;
|
||||
Health *hp = ecs_get_mut(world_ecs(), plr, Health);
|
||||
hp->hp = hp->max_hp = 999999;
|
||||
}
|
||||
nk_end(game_ui);
|
||||
}
|
||||
#endif
|
||||
|
||||
game_draw_ui();
|
||||
}
|
||||
EndDrawing();
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
#define MOB_SPAWN_DELAY (uint16_t)(20*1.5f)
|
||||
#define MOB_SPAWN_PERCENTAGE_FROM_MAX 0.05f
|
||||
#define MOB_INITIAL_MAX 50
|
||||
#define MOB_HARD_CAP 5000
|
||||
#define MOB_GROWTH_FACTOR 0.65f
|
||||
#define MOB_GROWTH_CONTROL 1.17f
|
||||
#define MOB_SPAWN_DIST 12*WORLD_BLOCK_SIZE;
|
||||
#define MOB_SPAWN_DIST 22*WORLD_BLOCK_SIZE;
|
||||
#define MOB_MAX_SPAWN_TRIES 5
|
||||
|
||||
uint64_t mob_kills = 0;
|
||||
static uint64_t max_mobs = MOB_INITIAL_MAX;
|
||||
static uint64_t mob_kills = 0;
|
||||
static uint16_t mob_spawn_timer = MOB_SPAWN_DELAY;
|
||||
static int16_t player_spawn_counter = -1;
|
||||
|
||||
void recalc_max_mobs() {
|
||||
max_mobs = (uint64_t)(MOB_INITIAL_MAX + MOB_GROWTH_FACTOR * zpl_pow((float)mob_kills, MOB_GROWTH_CONTROL));
|
||||
max_mobs = zpl_min(MOB_HARD_CAP, (uint64_t)(MOB_INITIAL_MAX + MOB_GROWTH_FACTOR * zpl_pow((float)mob_kills, MOB_GROWTH_CONTROL)));
|
||||
}
|
||||
|
||||
void MobDetectPlayers(ecs_iter_t *it) {
|
||||
|
|
|
@ -135,6 +135,7 @@ void WeaponProjectileHit(ecs_iter_t* it) {
|
|||
|
||||
pawn_velocity[j].x += (dx/dd)*WEAPON_HIT_FORCE_PUSH;
|
||||
pawn_velocity[j].y += (dy/dd)*WEAPON_HIT_FORCE_PUSH;
|
||||
entity_despawn(it->entities[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue