#include "all.h" Font DefaultFont(char * choice) { Font font = LoadFont(choice); if (!IsFontValid(font)) { font = GetFontDefault(); } return font; } void GameFrame(game_t * game, size_t frame, float x, float y) { game->frame_x[frame] = x; game->frame_y[frame] = y; } void GameFrameReset(game_t * game) { GameFrame(game, 0, game->horizontal/3, game->vertical - game->vertical/8); /* GameFrame(game, 1, game->horizontal/12, game->vertical/12); */ /* GameFrame(game, 2, game->horizontal - game->horizontal/4, game->vertical/12); */ } Vector2 GameFrameVector(game_t * game, size_t frame) { return (Vector2) { game->frame_x[frame], game->frame_y[frame]}; } void GameInitialize(game_t * game, char * window_name) { SetConfigFlags(FLAG_WINDOW_RESIZABLE); /* tell raylib to shut up */ SetTraceLogLevel(LOG_NONE); InitWindow(game->horizontal, game->vertical, window_name); SetWindowState(FLAG_WINDOW_HIDDEN); InitAudioDevice(); SetWindowPosition(0, 0); /* :config */ game->horizontal = 1920; game->vertical = 1080; game->ups = 60; game->fps = 30; game->font = DefaultFont("fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Bold.otf"); GameFrameReset(game); } void GameDeinitialize(game_t * game) { SetWindowState(FLAG_WINDOW_HIDDEN); UnloadFont(game->font); CloseAudioDevice(); CloseWindow(); } void GameLoop(game_t * game) { extern int Update(game_t * game, struct timespec now); extern void Frame(game_t * game, double interpolation); #define StepStart(prefix) \ prefix##_delta = timespec_sub(now, prefix##_last); \ if (timespec_cmp(prefix##_delta, prefix##_interval) >= 0) { (void) 0 #define StepStop(prefix) \ prefix##s_per_second++; \ prefix##_total++; \ prefix##_last = timespec_add(prefix##_last, prefix##_interval); \ if (timespec_cmp(prefix##_last, now) < 0) { \ prefix##_last = now; \ } \ } #define StepSimpleStart(prefix,linear) \ prefix##_delta = timespec_sub(now, prefix##_last); \ if (timespec_cmp(prefix##_delta, (struct timespec){1.,0.}) >= 0) { \ (void)0 #define StepSimpleStop(prefix) \ prefix##_last = now; \ } struct timespec now, update_interval = {0, (double) TIMESPEC_HZ / game->ups}, frame_interval = {0, (double) TIMESPEC_HZ / game->fps}, update_last, frame_last, print_last, update_delta, frame_delta, print_delta, wait; uint32_t updates_per_second = 0, frames_per_second = 0, frame_total = 0, update_total = 0; double interpolation = 0.; ClearWindowState(FLAG_WINDOW_HIDDEN); clock_gettime(CLOCK_MONOTONIC, &now); update_last = frame_last = print_last = now; while (1) { StepStart(update); if (Update(game, now)) { return; } StepStop(update); StepStart(frame); clock_gettime(CLOCK_MONOTONIC, &now); interpolation = CLAMP( TIMESPEC_TO_DOUBLE(update_delta) / TIMESPEC_TO_DOUBLE(update_interval), 0.0, 1.0f); Frame(game, interpolation); StepStop(frame); clock_gettime(CLOCK_MONOTONIC, &now); wait = timespec_sub( timespec_min( timespec_add(update_last, update_interval), timespec_add(frame_last, frame_interval)), now); if (timespec_cmp(wait, zero_seconds) > 0) { nanosleep(&wait, NULL); } StepSimpleStart(print, one_second); printf("[FPS|UPS|Total] (%3.0f : %3.0f) | [%7u/%7u]\n", round(frames_per_second / TIMESPEC_TO_DOUBLE(print_delta)), round(updates_per_second / TIMESPEC_TO_DOUBLE(print_delta)), frame_total, update_total); frames_per_second = updates_per_second = 0; StepSimpleStop(print); clock_gettime(CLOCK_MONOTONIC, &now); } }