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 VSYNC_ENABLED 0
|
||||||
|
|
||||||
#define GAME_FPS 30
|
#define GAME_FPS 30
|
||||||
|
|
||||||
#define USER_FRAME_LIMIT 300
|
#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;
|
b32 shutdown;
|
||||||
struct sys_thread game_thread;
|
struct sys_thread game_thread;
|
||||||
|
|
||||||
f64 timescale;
|
|
||||||
struct world world;
|
struct world world;
|
||||||
|
|
||||||
/* Game thread input */
|
/* Game thread input */
|
||||||
@ -66,9 +65,7 @@ INTERNAL struct game_cmd_array pop_cmds(struct arena *arena)
|
|||||||
INTERNAL void publish_game_tick(void)
|
INTERNAL void publish_game_tick(void)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
sys_mutex_lock(&L.published_tick_mutex);
|
sys_mutex_lock(&L.published_tick_mutex);
|
||||||
L.world.tick_published_ts = sys_timestamp();
|
|
||||||
world_copy_replace(&L.published_tick, &L.world);
|
world_copy_replace(&L.published_tick, &L.world);
|
||||||
sys_mutex_unlock(&L.published_tick_mutex);
|
sys_mutex_unlock(&L.published_tick_mutex);
|
||||||
}
|
}
|
||||||
@ -211,7 +208,8 @@ INTERNAL void game_update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
++L.world.tick_id;
|
++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;
|
L.world.time += L.world.dt;
|
||||||
struct entity_array entities_array = world_get_entities(&L.world);
|
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)) {
|
if (entity_has_prop(ent, ENTITY_PROP_TEST_SOUND_EMITTER)) {
|
||||||
struct mixer_desc desc = ent->sound_desc;
|
struct mixer_desc desc = ent->sound_desc;
|
||||||
desc.speed = L.timescale;
|
desc.speed = L.world.timescale;
|
||||||
desc.pos = ent->world_xform.og;
|
desc.pos = ent->world_xform.og;
|
||||||
struct sound *sound = sound_load_async(ent->sound_name, 0);
|
struct sound *sound = sound_load_async(ent->sound_name, 0);
|
||||||
b32 played = ent->sound_handle.gen != 0;
|
b32 played = ent->sound_handle.gen != 0;
|
||||||
@ -486,7 +484,7 @@ INTERNAL void game_thread_entry_point(void *arg)
|
|||||||
{
|
{
|
||||||
(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 (!L.shutdown) {
|
while (!L.shutdown) {
|
||||||
__profscope(game_update_w_sleep);
|
__profscope(game_update_w_sleep);
|
||||||
sleep_frame(last_frame_ts, target_dt);
|
sleep_frame(last_frame_ts, target_dt);
|
||||||
@ -509,7 +507,7 @@ void game_startup(void)
|
|||||||
L.published_tick_mutex = sys_mutex_alloc();
|
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"));
|
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 "sound.h"
|
||||||
#include "mixer.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 {
|
struct view {
|
||||||
f32 px_per_unit;
|
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 *from_tick = oldest_tick;
|
||||||
struct world *to_tick = newest_tick;
|
struct world *to_tick = newest_tick;
|
||||||
for (struct blend_tick *bt = L.head_blend_tick; bt; bt = bt->next) {
|
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;
|
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;
|
to_tick = &bt->world;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,8 +227,8 @@ INTERNAL struct interp_ticks pull_ticks(f64 blend_time)
|
|||||||
u64 bts_to_free_count = 0;
|
u64 bts_to_free_count = 0;
|
||||||
|
|
||||||
for (struct blend_tick *bt = L.head_blend_tick; bt; bt = bt->next) {
|
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 < sys_timestamp_seconds(from_tick->tick_published_ts)) {
|
if (bt_time < sys_timestamp_seconds(from_tick->tick_ts)) {
|
||||||
*arena_push(scratch.arena, struct blend_tick *) = bt;
|
*arena_push(scratch.arena, struct blend_tick *) = bt;
|
||||||
++bts_to_free_count;
|
++bts_to_free_count;
|
||||||
}
|
}
|
||||||
@ -588,7 +584,7 @@ INTERNAL void user_update(void)
|
|||||||
/* Pull ticks */
|
/* Pull ticks */
|
||||||
|
|
||||||
/* FIXME: use real game DT */
|
/* 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;
|
f64 blend_time = L.time > blend_time_offset ? L.time - blend_time_offset : 0;
|
||||||
|
|
||||||
struct interp_ticks interp_ticks = pull_ticks(blend_time);
|
struct interp_ticks interp_ticks = pull_ticks(blend_time);
|
||||||
@ -599,8 +595,8 @@ INTERNAL void user_update(void)
|
|||||||
{
|
{
|
||||||
__profscope(produce_interpolated_tick);
|
__profscope(produce_interpolated_tick);
|
||||||
|
|
||||||
f64 t0_time = sys_timestamp_seconds(t0->tick_published_ts);
|
f64 t0_time = sys_timestamp_seconds(t0->tick_ts);
|
||||||
f64 t1_time = sys_timestamp_seconds(t1->tick_published_ts);
|
f64 t1_time = sys_timestamp_seconds(t1->tick_ts);
|
||||||
|
|
||||||
f32 tick_blend = 0;
|
f32 tick_blend = 0;
|
||||||
if (t1_time > t0_time) {
|
if (t1_time > t0_time) {
|
||||||
@ -939,7 +935,7 @@ INTERNAL void user_thread_entry_point(void *arg)
|
|||||||
(UNUSED)arg;
|
(UNUSED)arg;
|
||||||
|
|
||||||
sys_timestamp_t last_frame_ts = 0;
|
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) {
|
while (!L.shutdown) {
|
||||||
__profscope(user_update_w_sleep);
|
__profscope(user_update_w_sleep);
|
||||||
|
|||||||
@ -5,8 +5,10 @@
|
|||||||
|
|
||||||
struct world {
|
struct world {
|
||||||
u64 tick_id; /* Starts at 1 */
|
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 dt;
|
||||||
f64 time;
|
f64 time;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user