summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSilvan Jegen <silvan@homearch>2019-04-19 18:43:37 +0200
committerSilvan Jegen <silvan@homearch>2019-04-19 18:43:37 +0200
commitb58d54ff235f9c03bf688963964a1077bb71ab5a (patch)
tree1b81c7e0e9a555a68826699c701169ab25f9be3d
parente168efe028dec4073d85d988de49cc8c642c6b39 (diff)
game: render at 60FPS and animate player accordingly
The input handling is not yet properly working.
-rw-r--r--game.c103
1 files 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 <time.h>
+#include <unistd.h>
+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