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 |
1.1 --- a/src/ascension/context.h Thu Mar 28 23:30:21 2024 +0100 1.2 +++ b/src/ascension/context.h Fri Mar 29 00:03:25 2024 +0100 1.3 @@ -55,8 +55,8 @@ 1.4 unsigned int fonts_loaded; 1.5 AscFont const *active_font; 1.6 asc_col4i ink; 1.7 - unsigned int elapsed_millis; 1.8 - float elapsed; 1.9 + uint64_t frame_nanos; 1.10 + uint64_t total_nanos; 1.11 } AscContext; 1.12 1.13 /** Global ascension context. */
2.1 --- a/src/ascension/datatypes.h Thu Mar 28 23:30:21 2024 +0100 2.2 +++ b/src/ascension/datatypes.h Fri Mar 29 00:03:25 2024 +0100 2.3 @@ -37,6 +37,14 @@ 2.4 #include <SDL2/SDL_pixels.h> 2.5 2.6 // -------------------------------------------------------------------------- 2.7 +// Useful Macros 2.8 +// -------------------------------------------------------------------------- 2.9 + 2.10 +#define ASC_NANOS_SECOND 1000000000ull 2.11 +#define ASC_NANOS_MILLISECOND 1000000ull 2.12 +#define ASC_NANOS_MICROSECOND 1000000ull 2.13 + 2.14 +// -------------------------------------------------------------------------- 2.15 // Datatype Definitions 2.16 // -------------------------------------------------------------------------- 2.17
3.1 --- a/src/context.c Thu Mar 28 23:30:21 2024 +0100 3.2 +++ b/src/context.c Fri Mar 29 00:03:25 2024 +0100 3.3 @@ -33,8 +33,16 @@ 3.4 #include <SDL2/SDL.h> 3.5 #include <SDL2/SDL_ttf.h> 3.6 3.7 +#include <time.h> 3.8 + 3.9 AscContext asc_context; 3.10 3.11 +static uint64_t asc_nanos(void) { 3.12 + struct timespec ts; 3.13 + clock_gettime(CLOCK_MONOTONIC, &ts); 3.14 + return 1000000000ull*(uint64_t)ts.tv_sec + (uint64_t)ts.tv_nsec; 3.15 +} 3.16 + 3.17 void asc_context_initialize(void) { 3.18 if (asc_test_flag(asc_context.flags, ASC_FLAG_INITILIZED)) 3.19 return; 3.20 @@ -58,6 +66,7 @@ 3.21 } 3.22 } 3.23 SDL_ClearError(); 3.24 + asc_context.total_nanos = asc_nanos(); 3.25 asc_set_flag(&asc_context.flags, ASC_FLAG_INITILIZED); 3.26 asc_dprintf("Ascension context initialized."); 3.27 } 3.28 @@ -128,11 +137,13 @@ 3.29 } 3.30 3.31 // compute frame time 3.32 - static Uint32 ticks; 3.33 - Uint32 ticks_elapsed = SDL_GetTicks() - ticks; 3.34 - ticks = SDL_GetTicks(); 3.35 - asc_context.elapsed_millis = ticks_elapsed; 3.36 - asc_context.elapsed = (float) ticks_elapsed / 1000.0f; 3.37 + uint64_t frame_nanos, ns; 3.38 + do { 3.39 + ns = asc_nanos(); 3.40 + frame_nanos = ns - asc_context.total_nanos; 3.41 + } while (frame_nanos == 0); 3.42 + asc_context.frame_nanos = frame_nanos; 3.43 + asc_context.total_nanos = ns; 3.44 3.45 return !asc_test_flag(asc_context.flags, ASC_FLAG_QUIT); 3.46 }
4.1 --- a/test/snake.c Thu Mar 28 23:30:21 2024 +0100 4.2 +++ b/test/snake.c Fri Mar 29 00:03:25 2024 +0100 4.3 @@ -29,18 +29,17 @@ 4.4 #include <cx/printf.h> 4.5 4.6 static void update_fps_counter(AscSceneNode *node) { 4.7 - // addition and multiplication is more efficient testing for zero 4.8 - // at an unnoticeable cost of imprecision 4.9 - static unsigned last_fps = 0u; 4.10 - static unsigned debounce = 999u; 4.11 - unsigned fps = 1000u; 4.12 - debounce += asc_context.elapsed_millis; 4.13 - if (debounce >= 1000u) { 4.14 + static uint64_t last_fps = 0; 4.15 + static uint64_t debounce = ASC_NANOS_SECOND - 1; 4.16 + debounce += asc_context.frame_nanos; 4.17 + // only update text every seconds 4.18 + if (debounce >= ASC_NANOS_SECOND) { 4.19 debounce = 0; 4.20 - fps /= asc_context.elapsed_millis; 4.21 + uint64_t fps = ASC_NANOS_SECOND; 4.22 + fps /= asc_context.frame_nanos; 4.23 if (fps != last_fps) { 4.24 last_fps = fps; 4.25 - snprintf(asc_text_data(node)->text, 9, "%u FPS", fps); 4.26 + snprintf(asc_text_data(node)->text, 11, "%"PRIu64" FPS", fps); 4.27 asc_node_update(node); 4.28 } 4.29 } 4.30 @@ -49,7 +48,7 @@ 4.31 static void create_fps_counter(void) { 4.32 asc_set_font(asc_font(ASC_FONT_REGULAR, 24)); 4.33 asc_ink_rgb(255, 0, 0); 4.34 - AscSceneNode* node = asc_text(10, 10, "XXXXX FPS"); 4.35 + AscSceneNode* node = asc_text(10, 10, "XXXXXXX FPS"); 4.36 asc_scene_add_behavior(node, update_fps_counter); 4.37 asc_scene_add(&asc_window_active->ui, node); 4.38 }