game tick continuity gen. start removing static constraint lookup

This commit is contained in:
jacob 2024-10-30 14:47:17 -05:00
parent c071e17305
commit f5e45d6ba1
6 changed files with 117 additions and 67 deletions

View File

@ -77,21 +77,6 @@ void entity_store_copy_replace(struct entity_store *dest, struct entity_store *s
dest->entities = dest_entities;
}
void entity_store_release_all_entities(struct entity_store *store)
{
#if 0
store->allocated = 0;
store->reserved = 0;
store->first_free = entity_nil_handle();
arena_pop_to(&store->arena, STORE_ENTITIES_OFFSET);
store_make_root(store);
#else
struct entity *root = entity_from_handle(store, store->root);
entity_release(store, root);
store_make_root(store);
#endif
}
/* ========================== *
* Allocation
* ========================== */

View File

@ -436,7 +436,6 @@ INLINE b32 entity_is_valid_and_active(struct entity *ent)
struct entity_store *entity_store_alloc(void);
void entity_store_release(struct entity_store *store);
void entity_store_copy_replace(struct entity_store *dest, struct entity_store *src);
void entity_store_release_all_entities(struct entity_store *store);
/* Entity */
struct entity *entity_alloc(struct entity *parent);

View File

@ -24,6 +24,7 @@ GLOBAL struct {
/* TODO: Remove this (testing) */
b32 extra_spawn;
b32 should_reset_level;
/* Game thread input */
struct sys_mutex game_cmds_mutex;
@ -39,6 +40,7 @@ GLOBAL struct {
/* Ticks */
struct sys_mutex prev_tick_mutex;
struct atomic_u64 prev_tick_id;
struct atomic_u64 prev_tick_continuity_gen;
struct world prev_tick;
struct world tick;
} G = ZI, DEBUG_ALIAS(G, G_game);
@ -49,6 +51,7 @@ GLOBAL struct {
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(game_shutdown);
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg);
INTERNAL void reset_world(void);
struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
struct sprite_startup_receipt *sheet_sr,
@ -79,14 +82,15 @@ struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
G.game_cmds_mutex = sys_mutex_alloc();
G.game_cmds_arena = arena_alloc(GIGABYTE(64));
/* Initialize ticks */
world_alloc(&G.tick);
/* Initialize empty world */
reset_world();
/* Initialize prev tick */
world_alloc(&G.prev_tick);
/* FIXME: Make the world struct itself readonly as well */
arena_set_readonly(&G.prev_tick.entity_store->arena);
G.prev_tick_mutex = sys_mutex_alloc();
G.tick.timescale = GAME_TIMESCALE;
G.game_thread = sys_thread_alloc(&game_thread_entry_point, NULL, STR("[P2] Game thread"));
app_register_exit_callback(&game_shutdown);
@ -139,6 +143,22 @@ INTERNAL void activate_now(struct entity *ent)
++ent->continuity_gen;
}
/* ========================== *
* Reset
* ========================== */
INTERNAL void reset_world(void)
{
if (G.tick.entity_store) {
/* Release world */
world_release(&G.tick);
}
/* Re-create world */
world_alloc(&G.tick);
G.tick.continuity_gen = atomic_u64_eval(&G.prev_tick_continuity_gen) + 1;
G.tick.timescale = GAME_TIMESCALE;
}
/* ========================== *
* Test
* ========================== */
@ -206,8 +226,7 @@ INTERNAL void spawn_test_entities(f32 offset)
entity_set_xform(e, xf);
e->linear_ground_friction = 250;
e->angular_ground_friction = 200;
e->linear_ground_friction = 250;e->angular_ground_friction = 200;
//e->control_force = 500;
e->control_force = 500;
@ -1351,6 +1370,7 @@ INTERNAL void publish_game_tick(void)
}
arena_set_readonly(&G.prev_tick.entity_store->arena);
atomic_u64_eval_exchange(&G.prev_tick_id, G.prev_tick.tick_id);
atomic_u64_eval_exchange(&G.prev_tick_continuity_gen, G.prev_tick.continuity_gen);
sys_mutex_unlock(&lock);
}
@ -1360,6 +1380,17 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
struct temp_arena scratch = scratch_begin_no_conflict();
/* ========================== *
* Reset level if necessary
* ========================== */
if (G.should_reset_level) {
logf_info("Clearing level");
G.should_reset_level = false;
G.extra_spawn = false;
reset_world();
}
/* ========================== *
* Begin frame
* ========================== */
@ -1412,9 +1443,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
/* Clear level */
case GAME_CMD_KIND_CLEAR_ALL:
{
logf_info("Clearing level");
entity_store_release_all_entities(store);
G.extra_spawn = false;
G.should_reset_level = true;
} break;
/* Spawn test */
@ -2235,6 +2264,11 @@ u64 game_get_latest_tick_id(void)
return atomic_u64_eval(&G.prev_tick_id);
}
u64 game_get_latest_tick_continuity_gen(void)
{
return atomic_u64_eval(&G.prev_tick_continuity_gen);
}
void game_push_cmds(struct game_cmd_array cmd_array)
{
push_cmds(cmd_array);

View File

@ -57,6 +57,7 @@ struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
void game_get_latest_tick(struct world *dest);
u64 game_get_latest_tick_id(void);
u64 game_get_latest_tick_continuity_gen(void);
void game_push_cmds(struct game_cmd_array cmd_array);

View File

@ -255,6 +255,9 @@ INTERNAL struct interp_ticks pull_ticks(f64 blend_time)
}
}
struct world *from_tick;
struct world *to_tick;
if (newest_tick && game_get_latest_tick_continuity_gen() == newest_tick->continuity_gen) {
/* Pull new tick from game thread if necessary */
if (!newest_tick || game_get_latest_tick_id() > newest_tick->tick_id) {
struct blend_tick *latest_bt = blend_tick_alloc();
@ -271,8 +274,8 @@ INTERNAL struct interp_ticks pull_ticks(f64 blend_time)
}
/* Find closest ticks to blend time */
struct world *from_tick = oldest_tick;
struct world *to_tick = newest_tick;
from_tick = oldest_tick;
to_tick = newest_tick;
for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) {
f64 bt_time = sys_timestamp_seconds(bt->world.tick_ts);
@ -305,6 +308,33 @@ INTERNAL struct interp_ticks pull_ticks(f64 blend_time)
scratch_end(scratch);
}
} else {
/* Latest tick is discontinuous */
/* Free all blend ticks */
{
struct temp_arena scratch = scratch_begin_no_conflict();
struct blend_tick **bts_to_free = arena_dry_push(scratch.arena, struct blend_tick *);
u64 bts_to_free_count = 0;
for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) {
*arena_push(scratch.arena, struct blend_tick *) = bt;
++bts_to_free_count;
}
for (u64 i = 0; i < bts_to_free_count; ++i) {
blend_tick_release(bts_to_free[i]);
}
scratch_end(scratch);
}
/* Allocate new blend tick */
struct blend_tick *bt = blend_tick_alloc();
struct world *tick = &bt->world;
game_get_latest_tick(tick);
from_tick = tick;
to_tick = tick;
}
return (struct interp_ticks) {
.from_tick = from_tick,

View File

@ -4,6 +4,7 @@
#include "entity.h"
struct world {
u64 continuity_gen; /* Starts at 1 */
u64 tick_id; /* Starts at 1 */
u64 tick_ts; /* When was this tick simulated in program time */