debug pausing

This commit is contained in:
jacob 2024-08-12 18:50:10 -05:00
parent ccbfc22e84
commit 81d02f3c80
6 changed files with 71 additions and 28 deletions

View File

@ -30,7 +30,7 @@
#define PIXELS_PER_UNIT 256.0 #define PIXELS_PER_UNIT 256.0
#define GAME_FPS 50.0 #define GAME_FPS 50.0
#define GAME_TIMESCALE 1.0 #define GAME_TIMESCALE 1
/* How many ticks back in time should the user blend between? /* How many ticks back in time should the user blend between?
* <Delay ms> = <USER_INTERP_OFFSET_TICK_RATIO> * <Game tick rate> * <Delay ms> = <USER_INTERP_OFFSET_TICK_RATIO> * <Game tick rate>

View File

@ -113,10 +113,11 @@ struct entity {
struct entity_handle equipped; struct entity_handle equipped;
/* ====================================================================== */ /* ====================================================================== */
/* Weapon */ /* Triggers */
/* ENTITY_PROP_WEAPON */ /* ENTITY_PROP_TRIGGERED_THIS_TICK */
f32 fire_rate; f32 trigger_delay; /* Minimum time between triggers */
f32 last_triggered;
/* ====================================================================== */ /* ====================================================================== */
/* Testing */ /* Testing */

View File

@ -15,6 +15,8 @@ GLOBAL struct {
struct atomic_i32 game_thread_shutdown; struct atomic_i32 game_thread_shutdown;
struct sys_thread game_thread; struct sys_thread game_thread;
b32 paused;
/* Game thread input */ /* Game thread input */
struct sys_mutex game_cmds_mutex; struct sys_mutex game_cmds_mutex;
struct arena game_cmds_arena; struct arena game_cmds_arena;
@ -101,7 +103,7 @@ INTERNAL struct game_cmd_array pop_cmds(struct arena *arena)
INTERNAL void spawn_test_entities(void) INTERNAL void spawn_test_entities(void)
{ {
/* Player ent */ /* Player */
struct entity *player_ent; struct entity *player_ent;
{ {
struct v2 pos = V2(1, 1); struct v2 pos = V2(1, 1);
@ -109,8 +111,11 @@ INTERNAL void spawn_test_entities(void)
f32 r = 0; f32 r = 0;
struct entity *e = entity_alloc_top(G.tick.entity_store); struct entity *e = entity_alloc_top(G.tick.entity_store);
entity_set_xform(e, XFORM_TRS(.t = pos, .r = r, .s = size));
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
entity_set_xform(e, xf);
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase")); e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
e->sprite_span_name = STR("idle.unarmed"); e->sprite_span_name = STR("idle.unarmed");
//e->sprite_span_name = STR("idle.one_handed"); //e->sprite_span_name = STR("idle.one_handed");
@ -121,33 +126,32 @@ INTERNAL void spawn_test_entities(void)
e->player_acceleration = 20.0f; e->player_acceleration = 20.0f;
e->control.focus = V2(0, -1); e->control.focus = V2(0, -1);
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
player_ent = e; player_ent = e;
//entity_enable_prop(e, ENTITY_PROP_TEST); //entity_enable_prop(e, ENTITY_PROP_TEST);
} }
/* Child 1 */ /* Weapon */
{ {
struct v2 pos = V2(1, 0); struct v2 pos = V2(1, 0);
struct v2 size = V2(1, 1); struct v2 size = V2(1, 1);
f32 r = PI / 4; f32 r = PI / 4;
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
struct entity *e = entity_alloc_top(G.tick.entity_store); struct entity *e = entity_alloc_top(G.tick.entity_store);
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
entity_set_local_xform(e, xf); entity_set_local_xform(e, xf);
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
e->sprite = sprite_tag_from_path(STR("res/graphics/gun.ase")); e->sprite = sprite_tag_from_path(STR("res/graphics/gun.ase"));
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
entity_enable_prop(e, ENTITY_PROP_WEAPON); entity_enable_prop(e, ENTITY_PROP_WEAPON);
e->trigger_delay = 1.0 / 10.0;
player_ent->equipped = e->handle; player_ent->equipped = e->handle;
} }
/* Camera ent */ /* Camera */
{ {
struct entity *e = entity_alloc_top(G.tick.entity_store); struct entity *e = entity_alloc_top(G.tick.entity_store);
entity_set_xform(e, XFORM_IDENT); entity_set_xform(e, XFORM_IDENT);
@ -179,7 +183,7 @@ INTERNAL void publish_game_tick(void)
sys_mutex_unlock(&lock); sys_mutex_unlock(&lock);
} }
INTERNAL void game_update(void) INTERNAL void game_update(struct game_cmd_array game_cmds)
{ {
__prof; __prof;
@ -194,7 +198,7 @@ INTERNAL void game_update(void)
G.tick.dt = max_f64(0.0, (1.0 / GAME_FPS) * G.tick.timescale); G.tick.dt = max_f64(0.0, (1.0 / GAME_FPS) * G.tick.timescale);
G.tick.time += G.tick.dt; G.tick.time += G.tick.dt;
struct game_cmd_array game_cmds = pop_cmds(scratch.arena); f64 time = G.tick.time;
struct entity_store *store = G.tick.entity_store; struct entity_store *store = G.tick.entity_store;
struct entity *root = entity_from_handle(store, store->root); struct entity *root = entity_from_handle(store, store->root);
struct sprite_scope *sprite_frame_scope = sprite_scope_begin(); struct sprite_scope *sprite_frame_scope = sprite_scope_begin();
@ -367,7 +371,7 @@ INTERNAL void game_update(void)
ent->test_start_sprite_xform = ent->sprite_local_xform; ent->test_start_sprite_xform = ent->sprite_local_xform;
} }
f32 t = ((f32)G.tick.time); f32 t = (f32)time;
struct v2 og = v2_mul(V2(math_cos(t), math_sin(t)), 3); struct v2 og = v2_mul(V2(math_cos(t), math_sin(t)), 3);
f32 r = t * 3; f32 r = t * 3;
struct v2 s = V2(1 + (math_fabs(math_sin(t * 5)) * 3), 1); struct v2 s = V2(1 + (math_fabs(math_sin(t * 5)) * 3), 1);
@ -406,17 +410,23 @@ INTERNAL void game_update(void)
} }
/* ========================== * /* ========================== *
* Fire weapons * Fire triggers
* ========================== */ * ========================== */
for (u64 entity_index = 0; entity_index < store->count; ++entity_index) { for (u64 entity_index = 0; entity_index < store->count; ++entity_index) {
struct entity *ent = &store->entities[entity_index]; struct entity *ent = &store->entities[entity_index];
if (!ent->valid) continue; if (!ent->valid) continue;
if (!entity_has_prop(ent, ENTITY_PROP_TRIGGERED_THIS_TICK)) continue;
if ((time - ent->last_triggered < ent->trigger_delay) && ent->last_triggered != 0) continue;
ent->last_triggered = time;
/* Fire weapon */
if (entity_has_prop(ent, ENTITY_PROP_WEAPON)) { if (entity_has_prop(ent, ENTITY_PROP_WEAPON)) {
if (entity_has_prop(ent, ENTITY_PROP_TRIGGERED_THIS_TICK)) { f32 r = 1.0f * ((f32)sys_rand_u32() / U32_MAX);
ent->sprite_tint = RGBA_32_F(1, 0, 0, 1); f32 g = 1.0f * ((f32)sys_rand_u32() / U32_MAX);
} f32 b = 1.0f * ((f32)sys_rand_u32() / U32_MAX);
ent->sprite_tint = RGBA_32_F(r, g, b, 1);
} }
} }
@ -661,15 +671,32 @@ INTERNAL void game_update(void)
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg) INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg)
{ {
struct temp_arena scratch = scratch_begin_no_conflict();
(UNUSED)arg; (UNUSED)arg;
sys_timestamp_t last_frame_ts = 0; sys_timestamp_t last_frame_ts = 0;
f64 target_dt = GAME_FPS > (0) ? (1.0 / GAME_FPS) : 0; f64 target_dt = GAME_FPS > (0) ? (1.0 / GAME_FPS) : 0;
while (!atomic_i32_eval(&G.game_thread_shutdown)) { while (!atomic_i32_eval(&G.game_thread_shutdown)) {
__profscope(game_update_w_sleep); __profscope(game_update_w_sleep);
struct temp_arena temp = arena_temp_begin(scratch.arena);
sleep_frame(last_frame_ts, target_dt); sleep_frame(last_frame_ts, target_dt);
last_frame_ts = sys_timestamp(); last_frame_ts = sys_timestamp();
game_update(); {
struct game_cmd_array game_cmds = pop_cmds(temp.arena);
if (!G.paused) {
game_update(game_cmds);
}
/* Check for pause cmd */
for (u64 i = 0; i < game_cmds.count; ++i) {
if (game_cmds.cmds[i].kind == GAME_CMD_KIND_PAUSE) {
G.paused = !G.paused;
}
}
}
arena_temp_end(temp);
} }
scratch_end(scratch);
} }
/* ========================== * /* ========================== *

View File

@ -21,6 +21,7 @@ enum game_cmd_kind {
/* Testing */ /* Testing */
GAME_CMD_KIND_CLEAR_ALL, GAME_CMD_KIND_CLEAR_ALL,
GAME_CMD_KIND_SPAWN_TEST, GAME_CMD_KIND_SPAWN_TEST,
GAME_CMD_KIND_PAUSE,
GAME_CMD_KIND_COUNT GAME_CMD_KIND_COUNT
}; };

View File

@ -86,8 +86,9 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
[SYS_BTN_C] = USER_BIND_KIND_DEBUG_CLEAR, [SYS_BTN_C] = USER_BIND_KIND_DEBUG_CLEAR,
[SYS_BTN_V] = USER_BIND_KIND_DEBUG_SPAWN, [SYS_BTN_V] = USER_BIND_KIND_DEBUG_SPAWN,
[SYS_BTN_F6] = USER_BIND_KIND_DEBUG_DRAW, [SYS_BTN_F1] = USER_BIND_KIND_DEBUG_PAUSE,
[SYS_BTN_F7] = USER_BIND_KIND_DEBUG_CAMERA, [SYS_BTN_F2] = USER_BIND_KIND_DEBUG_CAMERA,
[SYS_BTN_F3] = USER_BIND_KIND_DEBUG_DRAW,
[SYS_BTN_F11] = USER_BIND_KIND_FULLSCREEN, [SYS_BTN_F11] = USER_BIND_KIND_FULLSCREEN,
[SYS_BTN_MWHEELUP] = USER_BIND_KIND_ZOOM_IN, [SYS_BTN_MWHEELUP] = USER_BIND_KIND_ZOOM_IN,
[SYS_BTN_MWHEELDOWN] = USER_BIND_KIND_ZOOM_OUT, [SYS_BTN_MWHEELDOWN] = USER_BIND_KIND_ZOOM_OUT,
@ -575,6 +576,16 @@ INTERNAL void user_update(void)
} }
} }
/* Test pause */
{
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_PAUSE];
if (state.num_presses) {
queue_game_cmd(&cmd_list, (struct game_cmd) {
.kind = GAME_CMD_KIND_PAUSE
});
}
}
/* Test spawn */ /* Test spawn */
{ {
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN]; struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN];
@ -766,9 +777,10 @@ INTERNAL void user_update(void)
if (!ent->valid) continue; if (!ent->valid) continue;
if (ent->is_root) continue; if (ent->is_root) continue;
struct sprite_tag sprite = ent->sprite;
/* Skip undrawable entities */ /* Skip undrawable entities */
if (sprite_tag_is_nil(ent->sprite) if (sprite_tag_is_nil(sprite) && !entity_has_prop(ent, ENTITY_PROP_CAMERA)) {
&& !entity_has_prop(ent, ENTITY_PROP_CAMERA)) {
continue; continue;
} }
@ -783,13 +795,12 @@ INTERNAL void user_update(void)
struct xform sprite_xform = xf; struct xform sprite_xform = xf;
/* Draw sprite */ /* Draw sprite */
if (!sprite_tag_is_nil(ent->sprite)) { if (!sprite_tag_is_nil(sprite)) {
/* Calculate sprite xform */ /* Calculate sprite xform */
sprite_xform = xform_mul(xf, ent->sprite_local_xform); sprite_xform = xform_mul(xf, ent->sprite_local_xform);
/* Async load */ /* Async load */
struct sprite_tag sprite = ent->sprite;
struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite); struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite);
struct sprite_texture *texture = sprite_texture_from_tag_async(sprite_frame_scope, sprite); struct sprite_texture *texture = sprite_texture_from_tag_async(sprite_frame_scope, sprite);
(UNUSED)texture; (UNUSED)texture;
@ -863,7 +874,6 @@ INTERNAL void user_update(void)
/* Draw slices */ /* Draw slices */
if (!sprite_tag_is_nil(ent->sprite)) { if (!sprite_tag_is_nil(ent->sprite)) {
struct sprite_tag sprite = ent->sprite;
struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite); struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite);
for (u64 i = 0; i < sheet->slice_groups_count; ++i) { for (u64 i = 0; i < sheet->slice_groups_count; ++i) {
@ -1018,6 +1028,9 @@ INTERNAL void user_update(void)
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("time: %F"), FMT_FLOAT((f64)G.time))); draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("time: %F"), FMT_FLOAT((f64)G.time)));
pos.y += spacing; pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("world time: %F"), FMT_FLOAT((f64)G.world.time)));
pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("screen_size: (%F, %F)"), FMT_FLOAT((f64)G.screen_size.x), FMT_FLOAT((f64)G.screen_size.y))); draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("screen_size: (%F, %F)"), FMT_FLOAT((f64)G.screen_size.x), FMT_FLOAT((f64)G.screen_size.y)));
pos.y += spacing; pos.y += spacing;

View File

@ -26,6 +26,7 @@ enum user_bind_kind {
USER_BIND_KIND_DEBUG_SPAWN, USER_BIND_KIND_DEBUG_SPAWN,
USER_BIND_KIND_DEBUG_DRAW, USER_BIND_KIND_DEBUG_DRAW,
USER_BIND_KIND_DEBUG_CAMERA, USER_BIND_KIND_DEBUG_CAMERA,
USER_BIND_KIND_DEBUG_PAUSE,
USER_BIND_KIND_FULLSCREEN, USER_BIND_KIND_FULLSCREEN,
USER_BIND_KIND_ZOOM_IN, USER_BIND_KIND_ZOOM_IN,
USER_BIND_KIND_ZOOM_OUT, USER_BIND_KIND_ZOOM_OUT,