diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 114 |
1 files changed, 89 insertions, 25 deletions
diff --git a/src/main.c b/src/main.c index f86ed0b..922ca20 100644 --- a/src/main.c +++ b/src/main.c @@ -4,8 +4,8 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <inttypes.h> -#include <errno.h> +#include <errno.h> // ENOENT +#include <math.h> // used by vk2dSleep #include "input.h" #include "loader.h" @@ -14,8 +14,8 @@ #include "tilemap.h" -#include "incbin.h" -#include "libplum.h" +#include "incbin.h" // game icon +#include "libplum.h" // decoding game icon #include "main.h" @@ -240,10 +240,19 @@ int game_load_level(char *level) { game_state = STATE_FADE_OUT; fade = 255; - int x = (entities.player[0].x / 16) - (WINDOW_WIDTH / 2); - int y = (entities.player[0].y / 16) - (WINDOW_HEIGHT / 2); - if (x < 0) {x = 0;} else if (x + WINDOW_WIDTH > tilemap->width * 8) {x = tilemap->width * 8 - WINDOW_WIDTH;} - if (y < 0) {y = 0;} else if (y + WINDOW_HEIGHT > tilemap->height * 8) {y = tilemap->height * 8 - WINDOW_HEIGHT;} + int x, y; + if (tilemap->width < WINDOW_WIDTH / 8) { + x = -((WINDOW_WIDTH - tilemap->width * 8) / 2); + } else { + x = (entities.player[0].x / 16) - (WINDOW_WIDTH / 2); + if (x < 0) {x = 0;} else if (x + WINDOW_WIDTH > tilemap->width * 8) {x = tilemap->width * 8 - WINDOW_WIDTH;} + } + if (tilemap->height <= WINDOW_HEIGHT / 8) { + y = -((WINDOW_HEIGHT - tilemap->height * 8) / 2); + } else { + y = (entities.player[0].y / 16) - (WINDOW_HEIGHT / 2); + if (y < 0) {y = 0;} else if (y + WINDOW_HEIGHT > tilemap->height * 8) {y = tilemap->height * 8 - WINDOW_HEIGHT;} + } game_render(framebuffer, x, y); SDL_SetRenderTarget(renderer, NULL); @@ -264,6 +273,27 @@ void game_render_flush(SDL_Texture *framebuffer) { SDL_RenderPresent(renderer); } +// from libertea / <https://github.com/PaoloMazzon> +double getTime(void) { + static double time = -1; + if (time == -1) + time = SDL_GetPerformanceCounter(); + return (double)(SDL_GetPerformanceCounter() - time) / SDL_GetPerformanceFrequency(); +} + +// also from libertea / <https://github.com/PaoloMazzon> +void vk2dSleep(double seconds) { + if (seconds <= 0) + return; + double start = SDL_GetPerformanceCounter(); + double milliseconds = floor(seconds * 1000); + SDL_Delay(milliseconds); + while ((SDL_GetPerformanceCounter() - start) / (double)SDL_GetPerformanceFrequency() < seconds) { + volatile int i = 0; + (void) i; + } +} + int main(int const argc, char *const *const argv) { save_file_name = SDL_GetPrefPath("sylvie", "game"); save_file_name = SDL_realloc(save_file_name, strlen(save_file_name) + strlen("save.sav") + 1); @@ -349,12 +379,13 @@ int main(int const argc, char *const *const argv) { #if defined(__EMSCRIPTEN__) scale = 1; #else - if (scale <= 0) { // this looks very wrong + if (scale <= 0) { // because we used atoi, the user can set scale to -1 or something SDL_DisplayMode dm; if (SDL_GetDesktopDisplayMode(0, &dm) != 0) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "couldnt get desktop size", SDL_GetError(), NULL); - fprintf(stderr, "info: couldnt get desktop size %s\n", SDL_GetError()); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "couldnt get desktop size", SDL_GetError(), NULL); + fprintf(stderr, "warn: couldnt get desktop size %s\n", SDL_GetError()); flags |= SDL_WINDOW_RESIZABLE; + scale = 3; } else { int x = dm.w / 2 / WINDOW_WIDTH; int y = dm.h / 2 / WINDOW_HEIGHT; @@ -366,8 +397,10 @@ int main(int const argc, char *const *const argv) { if (scale == 0) { scale = 1; } - if (dm.refresh_rate != 60) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "refresh rate", "this game currently only runs well on 60Hz displays", NULL); + if (dm.refresh_rate < 59) { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "refresh rate", "your monitor appears to have a refresh rate below 60Hz, the game will run slower\n" + "you can compile the game from source to disable vsync, unlocking the framerate\n" + "TODO: disabling vsync without a recompile", NULL); } } } @@ -375,12 +408,15 @@ int main(int const argc, char *const *const argv) { window = SDL_CreateWindow(":3", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH * scale, WINDOW_HEIGHT * scale, flags | SDL_WINDOW_HIDDEN); if (window == NULL) { + fprintf(stderr, "failed to create the game window: %s\n", SDL_GetError()); goto end; } + SDL_SetWindowMinimumSize(window, WINDOW_WIDTH, WINDOW_HEIGHT); SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"); // hack, i dont wanna deal with windows discarding render textures renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_PRESENTVSYNC); if (renderer == NULL) { + fprintf(stderr, "failed to create a rendering context: %s\n", SDL_GetError()); goto end; } SDL_RenderSetLogicalSize(renderer, WINDOW_WIDTH, WINDOW_HEIGHT); @@ -410,18 +446,23 @@ int main(int const argc, char *const *const argv) { particle_tex = res_get_texture("particles").data; - player_new(&next_entities); FILE *file = fopen(save_file_name, "rb"); if (file == NULL) { if (errno != ENOENT) { perror(save_file_name); goto end; } + player_new(&next_entities); player_property(next_entities.player, "x", "40"); player_property(next_entities.player, "y", "64"); game_load_level("untitled"); } else { - game_load(file); + if (game_load(file)) { + fputs("the save file is corrupt!\n", stderr); + player_property(next_entities.player, "x", "40"); + player_property(next_entities.player, "y", "64"); + game_load_level("untitled"); + } } #if 0 struct blob blob = res_get_map("untitled"); @@ -477,6 +518,8 @@ void main_loop(void) { int x = 0, y = 0; while (1) { #endif + double const begin_time = getTime(); + input_pressed = input_held; SDL_Event evt; while (SDL_PollEvent(&evt)) { @@ -546,7 +589,7 @@ void main_loop(void) { i = evt.tfinger.fingerId; touch.positions[i].x = evt.tfinger.x; touch.positions[i].y = evt.tfinger.y; - printf("%" PRIu64 " %" PRIu64 " %f %f\n", evt.tfinger.touchId, evt.tfinger.fingerId, evt.tfinger.x, evt.tfinger.y); + //printf("%" PRIu64 " %" PRIu64 " %f %f\n", evt.tfinger.touchId, evt.tfinger.fingerId, evt.tfinger.x, evt.tfinger.y); reset_touch: touch.input_touch = 0; for (size_t i = 0; i < touch.allocated; i++) { @@ -642,14 +685,25 @@ void main_loop(void) { player_property(next_entities.player, "y", "64"); game_load_level("untitled"); } else { - game_load(file); + if (game_load(file)) { + fputs("the save file somehow corrupted itself!\n", stderr); + goto end; // better than freezing if the save file magically corrupts + } } } - x = (entities.player[0].x / 16) - (WINDOW_WIDTH / 2); - y = (entities.player[0].y / 16) - (WINDOW_HEIGHT / 2); - if (x < 0) {x = 0;} else if (x + WINDOW_WIDTH > tilemap->width * 8) {x = tilemap->width * 8 - WINDOW_WIDTH;} - if (y < 0) {y = 0;} else if (y + WINDOW_HEIGHT > tilemap->height * 8) {y = tilemap->height * 8 - WINDOW_HEIGHT;} + if (tilemap->width < WINDOW_WIDTH / 8) { + x = -((WINDOW_WIDTH - tilemap->width * 8) / 2); + } else { + x = (entities.player[0].x / 16) - (WINDOW_WIDTH / 2); + if (x < 0) {x = 0;} else if (x + WINDOW_WIDTH > tilemap->width * 8) {x = tilemap->width * 8 - WINDOW_WIDTH;} + } + if (tilemap->height <= WINDOW_HEIGHT / 8) { + y = -((WINDOW_HEIGHT - tilemap->height * 8) / 2); + } else { + y = (entities.player[0].y / 16) - (WINDOW_HEIGHT / 2); + if (y < 0) {y = 0;} else if (y + WINDOW_HEIGHT > tilemap->height * 8) {y = tilemap->height * 8 - WINDOW_HEIGHT;} + } game_render(framebuffer, x, y); game_render_flush(framebuffer); @@ -667,10 +721,18 @@ void main_loop(void) { if (fade == 255) { if (game_load_level(game_next_level)) { game_state = STATE_FADE_OUT; - x = (entities.player[0].x / 16) - (WINDOW_WIDTH / 2); - y = (entities.player[0].y / 16) - (WINDOW_HEIGHT / 2); - if (x < 0) {x = 0;} else if (x + WINDOW_WIDTH > tilemap->width * 8) {x = tilemap->width * 8 - WINDOW_WIDTH;} - if (y < 0) {y = 0;} else if (y + WINDOW_HEIGHT > tilemap->height * 8) {y = tilemap->height * 8 - WINDOW_HEIGHT;} + if (tilemap->width < WINDOW_WIDTH / 8) { + x = -((WINDOW_WIDTH - tilemap->width * 8) / 2); + } else { + x = (entities.player[0].x / 16) - (WINDOW_WIDTH / 2); + if (x < 0) {x = 0;} else if (x + WINDOW_WIDTH > tilemap->width * 8) {x = tilemap->width * 8 - WINDOW_WIDTH;} + } + if (tilemap->height <= WINDOW_HEIGHT / 8) { + y = -((WINDOW_HEIGHT - tilemap->height * 8) / 2); + } else { + y = (entities.player[0].y / 16) - (WINDOW_HEIGHT / 2); + if (y < 0) {y = 0;} else if (y + WINDOW_HEIGHT > tilemap->height * 8) {y = tilemap->height * 8 - WINDOW_HEIGHT;} + } game_render(framebuffer, x, y); SDL_SetRenderTarget(renderer, NULL); @@ -697,6 +759,8 @@ void main_loop(void) { #if defined(__EMSCRIPTEN__) return; #else + double const end_time = getTime(); + vk2dSleep(1.0/60.0 - (end_time - begin_time)); } #endif |