From b58d54ff235f9c03bf688963964a1077bb71ab5a Mon Sep 17 00:00:00 2001 From: Silvan Jegen Date: Fri, 19 Apr 2019 18:43:37 +0200 Subject: game: render at 60FPS and animate player accordingly The input handling is not yet properly working. --- game.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 73 insertions(+), 30 deletions(-) diff --git a/game.c b/game.c index a77234c..54e0581 100644 --- a/game.c +++ b/game.c @@ -2,19 +2,34 @@ #define PLAYER_IS_DEAD 2 #define PLAYER_HAS_WON 3 +#include +#include +void update_player_animation(struct level_struct *cur_level_state) { + // Cycle through the player's faces + cur_level_state->player_face++; + if (cur_level_state->player_face == 4) { + cur_level_state->player_face = 0; + } +} + // player_action moves the player // It returns one of the three PLAYER_ define values ( top of this file ) int player_action( signed int xdiff, signed int ydiff, struct level_struct *currentlevel ) { - // Find the tile the player moved into/onto using the player's current position + // no movent so we just update the animation + if (xdiff == 0 && ydiff == 0) { + update_player_animation(currentlevel); + return PLAYER_IS_OK; + } + + // Find the tile the player moved into/onto using the player's + // current position int newx = currentlevel->px + xdiff; int newy = currentlevel->py + ydiff; - // Cycle through the player's faces - currentlevel->player_face++; - if ( currentlevel->player_face == 4 ) currentlevel->player_face = 0; + update_player_animation(currentlevel); // Check to make sure these directions are not solid ( ie walls ) // and also to see if they are interactive ( ie buttons ) @@ -77,23 +92,46 @@ int player_action( signed int xdiff, signed int ydiff, struct level_struct *curr int play_level(SDL_Renderer* renderer, struct level_struct *currentlevel) { + struct timespec last_render; + last_render.tv_sec = 0; + last_render.tv_nsec = 0; + // Loop until the user completes the level int player_status = PLAYER_IS_OK; - while ( player_status == PLAYER_IS_OK ) - { - SDL_Event userinput; - - // WaitEvent is like PollEvent, but instead we pause the program's - // execution until we get input - SDL_WaitEvent( &userinput ); - render(renderer, currentlevel); + while ( player_status == PLAYER_IS_OK ) { + struct timespec start, end; + clock_gettime(CLOCK_MONOTONIC_RAW, &start); + + double since_last = (start.tv_sec - last_render.tv_sec) * 1000000 + (double)(start.tv_nsec - last_render.tv_nsec) / 1000; + double ms_since_last = (double)since_last/(double)1000; + printf("ms since last %f\n", ms_since_last); + if (last_render.tv_nsec == 0 || ms_since_last >= 16.5) { + printf("fps: %f\n", 1000 / ms_since_last); + render(renderer, currentlevel); + } else { + float sleep_ms = 16.5 - ms_since_last; + printf("not yet. Sleep for %f ms\n", sleep_ms); + if (sleep_ms > 0) { + usleep(sleep_ms * 1000); + } + continue; + } + + clock_gettime(CLOCK_MONOTONIC_RAW, &end); + + uint64_t delta_us = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_nsec - start.tv_nsec) / 1000; + double ms = (double)delta_us/(double)1000; + printf("time taken %f\n", ms); + + last_render = end; + SDL_Event userinput; + int got_event = SDL_PollEvent(&userinput); + // Player movement signed int y, x; - - if ( userinput.type == SDL_KEYDOWN ) - { + if ( userinput.type == SDL_KEYDOWN ) { switch ( userinput.key.keysym.sym ) { case SDLK_UP: @@ -133,23 +171,28 @@ int play_level(SDL_Renderer* renderer, struct level_struct *currentlevel) y = 0; break; } - - // Now move the player - player_status = player_action( x, y, currentlevel ); - - // Move all of the echidnas - run_all_echidnaAI_onestep( currentlevel ); + } - // And make sure we open/close red doors if any - // of them are stepping on red levers - check_echidna_on_switches( currentlevel ); - - // Check to see if the player has run into an echidna - if ( check_echidna_proximity( currentlevel ) == 1 ) player_status = PLAYER_IS_DEAD; - - // Show a losing screen if applicable - if (player_status == PLAYER_IS_DEAD) render_a_losingscreen(renderer, currentlevel); + // Now update the player state + player_status = player_action(x, y, currentlevel); + + // there was no event so there is nothing else to do + if (!got_event) { + continue; } + + // Move all of the echidnas + run_all_echidnaAI_onestep( currentlevel ); + + // And make sure we open/close red doors if any + // of them are stepping on red levers + check_echidna_on_switches( currentlevel ); + + // Check to see if the player has run into an echidna + if ( check_echidna_proximity( currentlevel ) == 1 ) player_status = PLAYER_IS_DEAD; + + // Show a losing screen if applicable + if (player_status == PLAYER_IS_DEAD) render_a_losingscreen(renderer, currentlevel); } // The code running play_level needs to know if too advance -- cgit v1.2.1-18-gbd029