fix entity gen comparison
This commit is contained in:
parent
53ae299816
commit
bac9d797b9
@ -64,6 +64,7 @@ struct entity *entity_alloc_unlinked(struct entity_store *store)
|
||||
/* Reuse from free list */
|
||||
entity = entity_from_handle(store, store->first_free);
|
||||
handle = entity->handle;
|
||||
++handle.gen;
|
||||
store->first_free = entity->next_free;
|
||||
} else {
|
||||
/* Make new */
|
||||
@ -122,7 +123,7 @@ struct entity_store *entity_get_store(struct entity *ent)
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns a valid entity or nil entity. Always safe to read result, need to check `valid` to write. */
|
||||
/* Returns a valid entity or read-only nil entity. Always safe to read result, need to check `valid` to write. */
|
||||
struct entity *entity_from_handle(struct entity_store *store, struct entity_handle handle)
|
||||
{
|
||||
if (handle.gen != 0 && handle.idx < store->count) {
|
||||
|
||||
@ -131,11 +131,6 @@ INLINE struct entity_handle entity_nil_handle(void)
|
||||
return (struct entity_handle) { 0 };
|
||||
}
|
||||
|
||||
INLINE b32 entity_handle_is_nil(struct entity_handle h)
|
||||
{
|
||||
return h.gen == 0;
|
||||
}
|
||||
|
||||
INLINE b32 entity_handle_eq(struct entity_handle a, struct entity_handle b)
|
||||
{
|
||||
return a.gen == b.gen && a.idx == b.idx;
|
||||
|
||||
113
src/game.c
113
src/game.c
@ -95,6 +95,56 @@ INTERNAL struct game_cmd_array pop_cmds(struct arena *arena)
|
||||
return array;
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Test
|
||||
* ========================== */
|
||||
|
||||
/* TODO: Remove this */
|
||||
|
||||
INTERNAL void spawn_test_entities(void)
|
||||
{
|
||||
/* Player ent */
|
||||
struct entity *player_ent;
|
||||
{
|
||||
struct v2 pos = V2(1, 1);
|
||||
struct v2 size = V2(1, 1);
|
||||
f32 r = 0;
|
||||
|
||||
struct entity *e = entity_alloc_top(G.world.entity_store);
|
||||
e->xform = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||
|
||||
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
|
||||
e->sprite_span_name = STR("idle.unarmed");
|
||||
//e->sprite_span_name = STR("idle.one_handed");
|
||||
//e->sprite_span_name = STR("idle.two_handed");
|
||||
|
||||
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
|
||||
e->player_max_speed = 4.f;
|
||||
e->player_acceleration = 20.0f;
|
||||
e->focus = V2(0, -1);
|
||||
|
||||
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
|
||||
|
||||
player_ent = e;
|
||||
|
||||
//entity_enable_prop(e, ENTITY_PROP_TEST);
|
||||
}
|
||||
|
||||
/* Camera ent */
|
||||
{
|
||||
struct entity *e = entity_alloc_top(G.world.entity_store);
|
||||
e->xform = XFORM_IDENT;
|
||||
|
||||
entity_enable_prop(e, ENTITY_PROP_CAMERA);
|
||||
entity_enable_prop(e, ENTITY_PROP_CAMERA_ACTIVE);
|
||||
e->camera_follow = player_ent->handle;
|
||||
|
||||
f32 width = (f32)DEFAULT_CAMERA_WIDTH;
|
||||
f32 height = (f32)DEFAULT_CAMERA_HEIGHT;
|
||||
e->camera_quad_xform = XFORM_TRS(.s = V2(width, height));
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Update
|
||||
* ========================== */
|
||||
@ -165,47 +215,7 @@ INTERNAL void game_update(void)
|
||||
static b32 run = 0;
|
||||
if (!run) {
|
||||
run = 1;
|
||||
|
||||
/* Player ent */
|
||||
struct entity *player_ent;
|
||||
{
|
||||
struct v2 pos = V2(1, 1);
|
||||
struct v2 size = V2(1, 1);
|
||||
f32 r = 0;
|
||||
|
||||
struct entity *e = entity_alloc_top(G.world.entity_store);
|
||||
e->xform = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||
|
||||
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
|
||||
e->sprite_span_name = STR("idle.unarmed");
|
||||
//e->sprite_span_name = STR("idle.one_handed");
|
||||
//e->sprite_span_name = STR("idle.two_handed");
|
||||
|
||||
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
|
||||
e->player_max_speed = 4.f;
|
||||
e->player_acceleration = 20.0f;
|
||||
e->focus = V2(0, -1);
|
||||
|
||||
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
|
||||
|
||||
player_ent = e;
|
||||
|
||||
//entity_enable_prop(e, ENTITY_PROP_TEST);
|
||||
}
|
||||
|
||||
/* Camera ent */
|
||||
{
|
||||
struct entity *e = entity_alloc_top(G.world.entity_store);
|
||||
e->xform = XFORM_IDENT;
|
||||
|
||||
entity_enable_prop(e, ENTITY_PROP_CAMERA);
|
||||
entity_enable_prop(e, ENTITY_PROP_CAMERA_ACTIVE);
|
||||
e->camera_follow = player_ent->handle;
|
||||
|
||||
f32 width = (f32)DEFAULT_CAMERA_WIDTH;
|
||||
f32 height = (f32)DEFAULT_CAMERA_HEIGHT;
|
||||
e->camera_quad_xform = XFORM_TRS(.s = V2(width, height));
|
||||
}
|
||||
spawn_test_entities();
|
||||
}
|
||||
|
||||
++G.world.tick_id;
|
||||
@ -237,12 +247,18 @@ INTERNAL void game_update(void)
|
||||
logf_info("Clearing level");
|
||||
for (u64 i = 0; i < entities_array.count; ++i) {
|
||||
struct entity *ent = &entities_array.entities[i];
|
||||
if (ent->valid) {
|
||||
if (ent->valid && !ent->root) {
|
||||
entity_release(G.world.entity_store, ent);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
/* Spawn test */
|
||||
case GAME_CMD_KIND_SPAWN_TEST: {
|
||||
logf_info("Spawning (test)");
|
||||
spawn_test_entities();
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
};
|
||||
}
|
||||
@ -255,6 +271,8 @@ INTERNAL void game_update(void)
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
struct entity_handle root_handle = G.world.entity_store->root;
|
||||
|
||||
/* ========================== *
|
||||
* Update sprite
|
||||
* ========================== */
|
||||
@ -262,7 +280,7 @@ INTERNAL void game_update(void)
|
||||
/* Recalculate world xforms */
|
||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||
struct entity *ent = &entities_array.entities[entity_index];
|
||||
if (ent->valid && !ent->parent.gen) {
|
||||
if (ent->valid && entity_handle_eq(ent->parent, root_handle)) {
|
||||
recalculate_world_xforms_recurse(ent);
|
||||
}
|
||||
}
|
||||
@ -320,7 +338,7 @@ INTERNAL void game_update(void)
|
||||
/* Recalculate world xforms */
|
||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||
struct entity *ent = &entities_array.entities[entity_index];
|
||||
if (ent->valid && !ent->parent.gen) {
|
||||
if (ent->valid && entity_handle_eq(ent->parent, root_handle)) {
|
||||
recalculate_world_xforms_recurse(ent);
|
||||
}
|
||||
}
|
||||
@ -420,7 +438,7 @@ INTERNAL void game_update(void)
|
||||
/* Recalculate world xforms */
|
||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||
struct entity *ent = &entities_array.entities[entity_index];
|
||||
if (ent->valid && !ent->parent.gen) {
|
||||
if (ent->valid && entity_handle_eq(ent->parent, root_handle)) {
|
||||
recalculate_world_xforms_recurse(ent);
|
||||
}
|
||||
}
|
||||
@ -467,7 +485,7 @@ INTERNAL void game_update(void)
|
||||
/* Recalculate world xforms */
|
||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||
struct entity *ent = &entities_array.entities[entity_index];
|
||||
if (ent->valid && !ent->parent.gen) {
|
||||
if (ent->valid && entity_handle_eq(ent->parent, root_handle)) {
|
||||
recalculate_world_xforms_recurse(ent);
|
||||
}
|
||||
}
|
||||
@ -543,7 +561,7 @@ INTERNAL void game_update(void)
|
||||
/* Recalculate world xforms */
|
||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||
struct entity *ent = &entities_array.entities[entity_index];
|
||||
if (ent->valid && !ent->parent.gen) {
|
||||
if (ent->valid && entity_handle_eq(ent->parent, root_handle)) {
|
||||
recalculate_world_xforms_recurse(ent);
|
||||
}
|
||||
}
|
||||
@ -584,6 +602,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg)
|
||||
|
||||
void game_get_latest_tick(struct world *dest)
|
||||
{
|
||||
__prof;
|
||||
struct sys_lock lock = sys_mutex_lock_e(&G.published_tick_mutex);
|
||||
world_copy_replace(dest, &G.published_tick);
|
||||
sys_mutex_unlock(&lock);
|
||||
|
||||
@ -14,6 +14,7 @@ enum game_cmd_kind {
|
||||
|
||||
/* Testing */
|
||||
GAME_CMD_KIND_CLEAR_ALL,
|
||||
GAME_CMD_KIND_SPAWN_TEST,
|
||||
|
||||
GAME_CMD_KIND_COUNT
|
||||
};
|
||||
|
||||
@ -115,7 +115,7 @@ INTERNAL struct track *track_alloc_locked(struct sys_lock *lock, struct sound *s
|
||||
if (next_free) {
|
||||
next_free->prev = NULL;
|
||||
}
|
||||
*track = (struct track) { 0 };
|
||||
*track = (struct track) { .gen = track->gen + 1 };
|
||||
} else {
|
||||
/* Allocate new */
|
||||
track = arena_push_zero(&G.track_arena, struct track);
|
||||
|
||||
@ -205,6 +205,7 @@ INTERNAL struct renderer_handle handle_alloc(void *data)
|
||||
slot = store->head_free;
|
||||
store->head_free = slot->next_free;
|
||||
slot->next_free = NULL;
|
||||
++slot->gen;
|
||||
} else {
|
||||
/* Or push onto arena */
|
||||
if (store->count + 1 >= HANDLE_IDX_MAX) {
|
||||
|
||||
@ -1585,7 +1585,9 @@ INTERNAL struct win32_thread *win32_thread_alloc_locked(struct sys_lock *lock)
|
||||
if (G.threads_first_free) {
|
||||
t = G.threads_first_free;
|
||||
G.threads_first_free = t->next;
|
||||
MEMZERO_STRUCT(t);
|
||||
*t = (struct win32_thread) {
|
||||
.gen = t->gen + 1
|
||||
};
|
||||
} else {
|
||||
t = arena_push_zero(&G.threads_arena, struct win32_thread);
|
||||
t->gen = 1;
|
||||
|
||||
50
src/user.c
50
src/user.c
@ -84,6 +84,7 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
|
||||
/* Testing */
|
||||
|
||||
[SYS_BTN_C] = USER_BIND_KIND_DEBUG_CLEAR,
|
||||
[SYS_BTN_V] = USER_BIND_KIND_DEBUG_SPAWN,
|
||||
[SYS_BTN_F6] = USER_BIND_KIND_DEBUG_DRAW,
|
||||
[SYS_BTN_F7] = USER_BIND_KIND_DEBUG_CAMERA,
|
||||
[SYS_BTN_F11] = USER_BIND_KIND_FULLSCREEN,
|
||||
@ -443,26 +444,29 @@ INTERNAL void user_update(void)
|
||||
struct entity_array world_entities = entity_store_as_array(G.world.entity_store);
|
||||
|
||||
u64 num_entities = min_u64(t0_entities.count, t1_entities.count);
|
||||
for (u64 i = 0; i < num_entities; ++i) {
|
||||
struct entity *e0 = &t0_entities.entities[i];
|
||||
struct entity *e1 = &t1_entities.entities[i];
|
||||
struct entity *e = &world_entities.entities[i];
|
||||
if (e0->handle.gen == e1->handle.gen && e0->continuity_gen == e1->continuity_gen) {
|
||||
e->xform = xform_lerp(e0->xform, e1->xform, tick_blend);
|
||||
e->xform_world = xform_lerp(e0->xform_world, e1->xform_world, tick_blend);
|
||||
{
|
||||
__profscope(tick_blending);
|
||||
for (u64 i = 0; i < num_entities; ++i) {
|
||||
struct entity *e0 = &t0_entities.entities[i];
|
||||
struct entity *e1 = &t1_entities.entities[i];
|
||||
struct entity *e = &world_entities.entities[i];
|
||||
if (e0->handle.gen == e1->handle.gen && e0->continuity_gen == e1->continuity_gen) {
|
||||
e->xform = xform_lerp(e0->xform, e1->xform, tick_blend);
|
||||
e->xform_world = xform_lerp(e0->xform_world, e1->xform_world, tick_blend);
|
||||
|
||||
e->acceleration = v2_lerp(e0->acceleration, e1->acceleration, tick_blend);
|
||||
e->velocity = v2_lerp(e0->velocity, e1->velocity, tick_blend);
|
||||
e->player_acceleration = math_lerp(e0->player_acceleration, e1->player_acceleration, tick_blend);
|
||||
e->focus = v2_lerp(e0->focus, e1->focus, tick_blend);
|
||||
e->acceleration = v2_lerp(e0->acceleration, e1->acceleration, tick_blend);
|
||||
e->velocity = v2_lerp(e0->velocity, e1->velocity, tick_blend);
|
||||
e->player_acceleration = math_lerp(e0->player_acceleration, e1->player_acceleration, tick_blend);
|
||||
e->focus = v2_lerp(e0->focus, e1->focus, tick_blend);
|
||||
|
||||
e->sprite_xform = xform_lerp(e0->sprite_xform, e1->sprite_xform, tick_blend);
|
||||
e->sprite_xform_world = xform_lerp(e0->sprite_xform_world, e1->sprite_xform_world, tick_blend);
|
||||
e->animation_time_in_frame = math_lerp64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend);
|
||||
e->animation_frame = (u32)math_round_to_int(math_lerp(e0->animation_frame, e1->animation_frame, tick_blend));
|
||||
e->sprite_xform = xform_lerp(e0->sprite_xform, e1->sprite_xform, tick_blend);
|
||||
e->sprite_xform_world = xform_lerp(e0->sprite_xform_world, e1->sprite_xform_world, tick_blend);
|
||||
e->animation_time_in_frame = math_lerp64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend);
|
||||
e->animation_frame = (u32)math_round_to_int(math_lerp(e0->animation_frame, e1->animation_frame, tick_blend));
|
||||
|
||||
e->camera_quad_xform = xform_lerp(e0->camera_quad_xform, e1->camera_quad_xform, tick_blend);
|
||||
e->camera_rel_xform_target = xform_lerp(e0->camera_rel_xform_target, e1->camera_rel_xform_target, tick_blend);
|
||||
e->camera_quad_xform = xform_lerp(e0->camera_quad_xform, e1->camera_quad_xform, tick_blend);
|
||||
e->camera_rel_xform_target = xform_lerp(e0->camera_rel_xform_target, e1->camera_rel_xform_target, tick_blend);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
@ -570,13 +574,23 @@ INTERNAL void user_update(void)
|
||||
/* Test clear world */
|
||||
{
|
||||
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR];
|
||||
if (state.num_presses || state.is_held) {
|
||||
if (state.num_presses) {
|
||||
queue_game_cmd(&cmd_list, (struct game_cmd) {
|
||||
.kind = GAME_CMD_KIND_CLEAR_ALL
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* Test spawn */
|
||||
{
|
||||
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN];
|
||||
if (state.num_presses) {
|
||||
queue_game_cmd(&cmd_list, (struct game_cmd) {
|
||||
.kind = GAME_CMD_KIND_SPAWN_TEST
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (G.bind_states[USER_BIND_KIND_DEBUG_DRAW].num_presses > 0) {
|
||||
G.debug_draw = !G.debug_draw;
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ enum user_bind_kind {
|
||||
/* Testing */
|
||||
|
||||
USER_BIND_KIND_DEBUG_CLEAR,
|
||||
USER_BIND_KIND_DEBUG_SPAWN,
|
||||
USER_BIND_KIND_DEBUG_DRAW,
|
||||
USER_BIND_KIND_DEBUG_CAMERA,
|
||||
USER_BIND_KIND_FULLSCREEN,
|
||||
|
||||
@ -176,7 +176,7 @@ INTERNAL struct work *work_alloc_locked(struct sys_lock *lock)
|
||||
G.free_work_head = work->next_free;
|
||||
*work = (struct work) {
|
||||
.condition_variable_finished = work->condition_variable_finished,
|
||||
.gen = work->gen
|
||||
.gen = work->gen + 1
|
||||
};
|
||||
} else {
|
||||
/* Make new */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user