Fri, 29 Mar 2024 00:03:25 +0100
make the timer have nanoseconds precision
src/ascension/context.h | file | annotate | diff | comparison | revisions | |
src/ascension/datatypes.h | file | annotate | diff | comparison | revisions | |
src/context.c | file | annotate | diff | comparison | revisions | |
test/snake.c | file | annotate | diff | comparison | revisions |
--- a/src/ascension/context.h Thu Mar 28 23:30:21 2024 +0100 +++ b/src/ascension/context.h Fri Mar 29 00:03:25 2024 +0100 @@ -55,8 +55,8 @@ unsigned int fonts_loaded; AscFont const *active_font; asc_col4i ink; - unsigned int elapsed_millis; - float elapsed; + uint64_t frame_nanos; + uint64_t total_nanos; } AscContext; /** Global ascension context. */
--- a/src/ascension/datatypes.h Thu Mar 28 23:30:21 2024 +0100 +++ b/src/ascension/datatypes.h Fri Mar 29 00:03:25 2024 +0100 @@ -37,6 +37,14 @@ #include <SDL2/SDL_pixels.h> // -------------------------------------------------------------------------- +// Useful Macros +// -------------------------------------------------------------------------- + +#define ASC_NANOS_SECOND 1000000000ull +#define ASC_NANOS_MILLISECOND 1000000ull +#define ASC_NANOS_MICROSECOND 1000000ull + +// -------------------------------------------------------------------------- // Datatype Definitions // --------------------------------------------------------------------------
--- a/src/context.c Thu Mar 28 23:30:21 2024 +0100 +++ b/src/context.c Fri Mar 29 00:03:25 2024 +0100 @@ -33,8 +33,16 @@ #include <SDL2/SDL.h> #include <SDL2/SDL_ttf.h> +#include <time.h> + AscContext asc_context; +static uint64_t asc_nanos(void) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return 1000000000ull*(uint64_t)ts.tv_sec + (uint64_t)ts.tv_nsec; +} + void asc_context_initialize(void) { if (asc_test_flag(asc_context.flags, ASC_FLAG_INITILIZED)) return; @@ -58,6 +66,7 @@ } } SDL_ClearError(); + asc_context.total_nanos = asc_nanos(); asc_set_flag(&asc_context.flags, ASC_FLAG_INITILIZED); asc_dprintf("Ascension context initialized."); } @@ -128,11 +137,13 @@ } // compute frame time - static Uint32 ticks; - Uint32 ticks_elapsed = SDL_GetTicks() - ticks; - ticks = SDL_GetTicks(); - asc_context.elapsed_millis = ticks_elapsed; - asc_context.elapsed = (float) ticks_elapsed / 1000.0f; + uint64_t frame_nanos, ns; + do { + ns = asc_nanos(); + frame_nanos = ns - asc_context.total_nanos; + } while (frame_nanos == 0); + asc_context.frame_nanos = frame_nanos; + asc_context.total_nanos = ns; return !asc_test_flag(asc_context.flags, ASC_FLAG_QUIT); }
--- a/test/snake.c Thu Mar 28 23:30:21 2024 +0100 +++ b/test/snake.c Fri Mar 29 00:03:25 2024 +0100 @@ -29,18 +29,17 @@ #include <cx/printf.h> static void update_fps_counter(AscSceneNode *node) { - // addition and multiplication is more efficient testing for zero - // at an unnoticeable cost of imprecision - static unsigned last_fps = 0u; - static unsigned debounce = 999u; - unsigned fps = 1000u; - debounce += asc_context.elapsed_millis; - if (debounce >= 1000u) { + static uint64_t last_fps = 0; + static uint64_t debounce = ASC_NANOS_SECOND - 1; + debounce += asc_context.frame_nanos; + // only update text every seconds + if (debounce >= ASC_NANOS_SECOND) { debounce = 0; - fps /= asc_context.elapsed_millis; + uint64_t fps = ASC_NANOS_SECOND; + fps /= asc_context.frame_nanos; if (fps != last_fps) { last_fps = fps; - snprintf(asc_text_data(node)->text, 9, "%u FPS", fps); + snprintf(asc_text_data(node)->text, 11, "%"PRIu64" FPS", fps); asc_node_update(node); } } @@ -49,7 +48,7 @@ static void create_fps_counter(void) { asc_set_font(asc_font(ASC_FONT_REGULAR, 24)); asc_ink_rgb(255, 0, 0); - AscSceneNode* node = asc_text(10, 10, "XXXXX FPS"); + AscSceneNode* node = asc_text(10, 10, "XXXXXXX FPS"); asc_scene_add_behavior(node, update_fps_counter); asc_scene_add(&asc_window_active->ui, node); }