From e254c99b38713303970526514f6ade21a2956faf Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 14 Oct 2024 23:16:02 -0400 Subject: [PATCH] examples/game/01-snake: Update game logic in AppIterate, don't use a timer. Reference Issue #11210. --- examples/game/01-snake/snake.c | 37 +++++++++++++--------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/examples/game/01-snake/snake.c b/examples/game/01-snake/snake.c index 8257e416d2..f1be83c4a3 100644 --- a/examples/game/01-snake/snake.c +++ b/examples/game/01-snake/snake.c @@ -57,8 +57,8 @@ typedef struct { SDL_Window *window; SDL_Renderer *renderer; - SDL_TimerID step_timer; SnakeContext snake_ctx; + Uint64 last_step; } AppState; SnakeCell snake_cell_at(const SnakeContext *ctx, char x, char y) @@ -208,16 +208,6 @@ void snake_step(SnakeContext *ctx) } } -static Uint32 sdl_timer_callback_(void *payload, SDL_TimerID timer_id, Uint32 interval) -{ - /* NOTE: snake_step is not called here directly for multithreaded concerns. */ - SDL_Event event; - SDL_zero(event); - event.type = SDL_EVENT_USER; - SDL_PushEvent(&event); - return interval; -} - static int handle_key_event_(SnakeContext *ctx, SDL_Scancode key_code) { switch (key_code) { @@ -250,14 +240,22 @@ static int handle_key_event_(SnakeContext *ctx, SDL_Scancode key_code) SDL_AppResult SDL_AppIterate(void *appstate) { - AppState *as; - SnakeContext *ctx; + AppState *as = (AppState *)appstate; + SnakeContext *ctx = &as->snake_ctx; + const Uint64 now = SDL_GetTicks(); SDL_FRect r; unsigned i; unsigned j; int ct; - as = (AppState *)appstate; - ctx = &as->snake_ctx; + + // run game logic if we're at or past the time to run it. + // if we're _really_ behind the time to run it, run it + // several times. + while ((now - as->last_step) >= STEP_RATE_IN_MILLISECONDS) { + snake_step(ctx); + as->last_step += STEP_RATE_IN_MILLISECONDS; + } + r.w = r.h = SNAKE_BLOCK_SIZE_IN_PIXELS; SDL_SetRenderDrawColor(as->renderer, 0, 0, 0, 255); SDL_RenderClear(as->renderer); @@ -321,10 +319,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) snake_initialize(&as->snake_ctx); - as->step_timer = SDL_AddTimer(STEP_RATE_IN_MILLISECONDS, sdl_timer_callback_, NULL); - if (as->step_timer == 0) { - return SDL_APP_FAILURE; - } + as->last_step = SDL_GetTicks(); return SDL_APP_CONTINUE; } @@ -335,9 +330,6 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) switch (event->type) { case SDL_EVENT_QUIT: return SDL_APP_SUCCESS; - case SDL_EVENT_USER: - snake_step(ctx); - break; case SDL_EVENT_KEY_DOWN: return handle_key_event_(ctx, event->key.scancode); } @@ -348,7 +340,6 @@ void SDL_AppQuit(void *appstate, SDL_AppResult result) { if (appstate != NULL) { AppState *as = (AppState *)appstate; - SDL_RemoveTimer(as->step_timer); SDL_DestroyRenderer(as->renderer); SDL_DestroyWindow(as->window); SDL_free(as);