interp tick ratio rather than time offset. set world tick timestamp at beginning of frame
This commit is contained in:
parent
8f33957bf9
commit
bac001947b
@ -11,4 +11,11 @@
|
||||
#define VSYNC_ENABLED 0
|
||||
|
||||
#define GAME_FPS 30
|
||||
|
||||
#define USER_FRAME_LIMIT 300
|
||||
|
||||
/* How many ticks back in time should the user blend between?
|
||||
* Delay ms = USER_INTERP_OFFSET_TICK_RATIO * Game tick rate
|
||||
* E.g: At 1.5, the user thread will render 49.5ms back in time (if game thread runs at 30FPS)
|
||||
*/
|
||||
#define USER_INTERP_OFFSET_TICK_RATIO 1.5
|
||||
|
||||
12
src/game.c
12
src/game.c
@ -13,7 +13,6 @@ GLOBAL struct {
|
||||
b32 shutdown;
|
||||
struct sys_thread game_thread;
|
||||
|
||||
f64 timescale;
|
||||
struct world world;
|
||||
|
||||
/* Game thread input */
|
||||
@ -66,9 +65,7 @@ INTERNAL struct game_cmd_array pop_cmds(struct arena *arena)
|
||||
INTERNAL void publish_game_tick(void)
|
||||
{
|
||||
__prof;
|
||||
|
||||
sys_mutex_lock(&L.published_tick_mutex);
|
||||
L.world.tick_published_ts = sys_timestamp();
|
||||
world_copy_replace(&L.published_tick, &L.world);
|
||||
sys_mutex_unlock(&L.published_tick_mutex);
|
||||
}
|
||||
@ -211,7 +208,8 @@ INTERNAL void game_update(void)
|
||||
}
|
||||
|
||||
++L.world.tick_id;
|
||||
L.world.dt = max_f64(0.0, (1.0 / GAME_FPS) * L.timescale);
|
||||
L.world.tick_ts = sys_timestamp();
|
||||
L.world.dt = max_f64(0.0, (1.0 / GAME_FPS) * L.world.timescale);
|
||||
L.world.time += L.world.dt;
|
||||
struct entity_array entities_array = world_get_entities(&L.world);
|
||||
|
||||
@ -454,7 +452,7 @@ INTERNAL void game_update(void)
|
||||
|
||||
if (entity_has_prop(ent, ENTITY_PROP_TEST_SOUND_EMITTER)) {
|
||||
struct mixer_desc desc = ent->sound_desc;
|
||||
desc.speed = L.timescale;
|
||||
desc.speed = L.world.timescale;
|
||||
desc.pos = ent->world_xform.og;
|
||||
struct sound *sound = sound_load_async(ent->sound_name, 0);
|
||||
b32 played = ent->sound_handle.gen != 0;
|
||||
@ -486,7 +484,7 @@ INTERNAL void game_thread_entry_point(void *arg)
|
||||
{
|
||||
(UNUSED)arg;
|
||||
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 (!L.shutdown) {
|
||||
__profscope(game_update_w_sleep);
|
||||
sleep_frame(last_frame_ts, target_dt);
|
||||
@ -509,7 +507,7 @@ void game_startup(void)
|
||||
L.published_tick_mutex = sys_mutex_alloc();
|
||||
|
||||
|
||||
L.timescale = 1.0;
|
||||
L.world.timescale = 1.0;
|
||||
L.game_thread = sys_thread_init(&game_thread_entry_point, NULL, STR("[P2] Game thread"));
|
||||
}
|
||||
|
||||
|
||||
22
src/user.c
22
src/user.c
@ -19,10 +19,6 @@
|
||||
#include "sound.h"
|
||||
#include "mixer.h"
|
||||
|
||||
/* How far back in time should the user blend between game ticks (in addition
|
||||
* to the existing 1-tick delay) */
|
||||
#define USER_INTERP_DELAY 0.005
|
||||
|
||||
struct view {
|
||||
f32 px_per_unit;
|
||||
|
||||
@ -213,13 +209,13 @@ INTERNAL struct interp_ticks pull_ticks(f64 blend_time)
|
||||
struct world *from_tick = oldest_tick;
|
||||
struct world *to_tick = newest_tick;
|
||||
for (struct blend_tick *bt = L.head_blend_tick; bt; bt = bt->next) {
|
||||
f64 bt_time = sys_timestamp_seconds(bt->world.tick_published_ts);
|
||||
f64 bt_time = sys_timestamp_seconds(bt->world.tick_ts);
|
||||
|
||||
if (bt_time < blend_time && bt_time > sys_timestamp_seconds(from_tick->tick_published_ts)) {
|
||||
if (bt_time < blend_time && bt_time > sys_timestamp_seconds(from_tick->tick_ts)) {
|
||||
from_tick = &bt->world;
|
||||
}
|
||||
|
||||
if (bt_time > blend_time && bt_time < sys_timestamp_seconds(to_tick->tick_published_ts)) {
|
||||
if (bt_time > blend_time && bt_time < sys_timestamp_seconds(to_tick->tick_ts)) {
|
||||
to_tick = &bt->world;
|
||||
}
|
||||
}
|
||||
@ -231,8 +227,8 @@ INTERNAL struct interp_ticks pull_ticks(f64 blend_time)
|
||||
u64 bts_to_free_count = 0;
|
||||
|
||||
for (struct blend_tick *bt = L.head_blend_tick; bt; bt = bt->next) {
|
||||
f64 bt_time = sys_timestamp_seconds(bt->world.tick_published_ts);
|
||||
if (bt_time < sys_timestamp_seconds(from_tick->tick_published_ts)) {
|
||||
f64 bt_time = sys_timestamp_seconds(bt->world.tick_ts);
|
||||
if (bt_time < sys_timestamp_seconds(from_tick->tick_ts)) {
|
||||
*arena_push(scratch.arena, struct blend_tick *) = bt;
|
||||
++bts_to_free_count;
|
||||
}
|
||||
@ -588,7 +584,7 @@ INTERNAL void user_update(void)
|
||||
/* Pull ticks */
|
||||
|
||||
/* FIXME: use real game DT */
|
||||
f64 blend_time_offset = USER_INTERP_DELAY + (1.0 / GAME_FPS);
|
||||
f64 blend_time_offset = (1.0 / GAME_FPS) * USER_INTERP_OFFSET_TICK_RATIO;
|
||||
f64 blend_time = L.time > blend_time_offset ? L.time - blend_time_offset : 0;
|
||||
|
||||
struct interp_ticks interp_ticks = pull_ticks(blend_time);
|
||||
@ -599,8 +595,8 @@ INTERNAL void user_update(void)
|
||||
{
|
||||
__profscope(produce_interpolated_tick);
|
||||
|
||||
f64 t0_time = sys_timestamp_seconds(t0->tick_published_ts);
|
||||
f64 t1_time = sys_timestamp_seconds(t1->tick_published_ts);
|
||||
f64 t0_time = sys_timestamp_seconds(t0->tick_ts);
|
||||
f64 t1_time = sys_timestamp_seconds(t1->tick_ts);
|
||||
|
||||
f32 tick_blend = 0;
|
||||
if (t1_time > t0_time) {
|
||||
@ -939,7 +935,7 @@ INTERNAL void user_thread_entry_point(void *arg)
|
||||
(UNUSED)arg;
|
||||
|
||||
sys_timestamp_t last_frame_ts = 0;
|
||||
f64 target_dt = USER_FRAME_LIMIT > 0 ? (1.0 / USER_FRAME_LIMIT) : 0;
|
||||
f64 target_dt = USER_FRAME_LIMIT > (0) ? (1.0 / USER_FRAME_LIMIT) : 0;
|
||||
|
||||
while (!L.shutdown) {
|
||||
__profscope(user_update_w_sleep);
|
||||
|
||||
@ -5,8 +5,10 @@
|
||||
|
||||
struct world {
|
||||
u64 tick_id; /* Starts at 1 */
|
||||
u64 tick_published_ts;
|
||||
u64 tick_ts; /* When was this tick simulated in program time */
|
||||
|
||||
/* World time */
|
||||
f64 timescale;
|
||||
f64 dt;
|
||||
f64 time;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user