From 55d22c6e36b6b575a971202cb62e53a3a6fb54cb Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Mon, 14 Jan 2019 00:26:18 -0500 Subject: add moves and header text, won bg animation, window title --- assets/roboto.ttf | Bin 0 -> 171676 bytes meson.build | 1 + src/sdl/color.c | 2 +- src/sdl/draw.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/sdl/draw.h | 2 + src/sdl/main.c | 75 +++++++++++++++++++++-------- 6 files changed, 198 insertions(+), 22 deletions(-) create mode 100644 assets/roboto.ttf diff --git a/assets/roboto.ttf b/assets/roboto.ttf new file mode 100644 index 0000000..2c97eea Binary files /dev/null and b/assets/roboto.ttf differ diff --git a/meson.build b/meson.build index 4c241e7..5c826a7 100644 --- a/meson.build +++ b/meson.build @@ -31,6 +31,7 @@ executable('sok-sdl', sources + [ 'src/sdl/main.c', ], dependencies: [ dependency('SDL2'), + dependency('SDL2_ttf'), libm, ]) diff --git a/src/sdl/color.c b/src/sdl/color.c index cb94095..16c7cfd 100644 --- a/src/sdl/color.c +++ b/src/sdl/color.c @@ -5,7 +5,7 @@ static const SDL_Color PALETTE[] = { { .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF }, // COLOR_BG - { .r = 0x00, .g = 0xFF, .b = 0x00, .a = 0xFF }, // COLOR_BG_WON + { .r = 0x00, .g = 0x66, .b = 0x00, .a = 0xFF }, // COLOR_BG_WON { .r = 0x66, .g = 0x66, .b = 0x66, .a = 0xFF }, // COLOR_WALL { .r = 0x00, .g = 0xFF, .b = 0x00, .a = 0xFF }, // COLOR_GOAL { .r = 0xFF, .g = 0x00, .b = 0x00, .a = 0xFF }, // COLOR_HOME diff --git a/src/sdl/draw.c b/src/sdl/draw.c index 4449b52..aa16bca 100644 --- a/src/sdl/draw.c +++ b/src/sdl/draw.c @@ -1,4 +1,5 @@ #include // bool +#include // sinf() #include "util.h" // warn()/die() #include "color.h" // set_color() #include "draw.h" @@ -251,17 +252,154 @@ DRAW_CBS = { }; #endif /* DRAW_SPRITES */ +static const SDL_Color +TEXT_COLORS[] = { + { 0xff, 0xff, 0xff, 0xff }, // fg + { 0x00, 0x00, 0x00, 0xff }, // bg +}; + +static void +draw_text( + draw_ctx_t * const draw_ctx, + const char * const buf, + const SDL_Rect * const rect +) { + // create surface + SDL_Surface *surface = TTF_RenderText_Shaded( + draw_ctx->font, + buf, + TEXT_COLORS[0], + TEXT_COLORS[1] + ); + + // check for error + if (!surface) { + die("TTF_RenderText_Blended(): %s", TTF_GetError()); + } + + // create texture + SDL_Texture *texture = SDL_CreateTextureFromSurface(draw_ctx->renderer, surface); + if (!texture) { + die("SDL_CreateTextureFromSurface(): %s", SDL_GetError()); + } + + // free surface + SDL_FreeSurface(surface); + + // render text + if (SDL_RenderCopy(draw_ctx->renderer, texture, NULL, rect)) { + die("SDL_RenderCopy(): %s", SDL_GetError()); + } + + // free texture + SDL_DestroyTexture(texture); +} + +static void +draw_level_text( + draw_ctx_t * const draw_ctx +) { + // build text + char buf[256]; + snprintf( + buf, sizeof(buf), + "%s: %s (#%zu)", + draw_ctx->level->pack, + draw_ctx->level->name, + *draw_ctx->level_num + ); + + // get renderer width + int renderer_w; + if (SDL_GetRendererOutputSize(draw_ctx->renderer, &renderer_w, NULL)) { + die("SDL_GetRendererOutputSize(): %s", SDL_GetError()); + } + + // get text size + int text_w, text_h; + if (TTF_SizeText(draw_ctx->font, buf, &text_w, &text_h)) { + die("TTF_SizeText(): %s", TTF_GetError()); + } + + // build rect + const SDL_Rect rect = { (renderer_w - text_w) / 2, 10, text_w, text_h }; + + // draw text + draw_text(draw_ctx, buf, &rect); +} + +static void +draw_moves_text( + draw_ctx_t * const draw_ctx +) { + // build text + char buf[256]; + snprintf(buf, sizeof(buf), "Moves: %zu", draw_ctx->ctx->num_moves); + + // get renderer height + int renderer_h; + if (SDL_GetRendererOutputSize(draw_ctx->renderer, NULL, &renderer_h)) { + die("SDL_GetRendererOutputSize(): %s", SDL_GetError()); + } + + // get text size + int text_w, text_h; + if (TTF_SizeText(draw_ctx->font, buf, &text_w, &text_h)) { + die("TTF_SizeText(): %s", TTF_GetError()); + } + + // build rect + const SDL_Rect rect = { 10, renderer_h - text_h - 10, text_w, text_h }; + + // draw text + draw_text(draw_ctx, buf, &rect); +} + +static void +set_bg_won_color( + draw_ctx_t * const draw_ctx +) { + const Uint32 ticks = SDL_GetTicks(); + + // gen color + const SDL_Color c = { + .r = 0x66 + 0x33 * sinf((1000 + ticks) * 2.0 * 3.14159 / 2000.0), + .g = 0x66 + 0x33 * sinf((3000 + ticks) * 2.0 * 3.14159 / 5000.0), + .b = 0x66 + 0x33 * sinf((5000 + ticks) * 2.0 * 3.14159 / 7000.0), + .a = 0xFF, + }; + + // set color + if (SDL_SetRenderDrawColor(draw_ctx->renderer, c.r, c.g, c.b, c.a)) { + die("SDL_SetRenderDrawColor(): %s", SDL_GetError()); + } +} + void draw( draw_ctx_t * const draw_ctx ) { + const bool is_done = sok_ctx_is_done(draw_ctx->ctx); + + // set bg color + if (sok_ctx_is_done(draw_ctx->ctx)) { + // set bg won color + set_bg_won_color(draw_ctx); + } else { + // set normal bg color + set_color(draw_ctx->renderer, is_done ? COLOR_BG_WON : COLOR_BG); + } + // clear background - set_color(draw_ctx->renderer, sok_ctx_is_done(draw_ctx->ctx) ? COLOR_BG_WON : COLOR_BG); SDL_RenderClear(draw_ctx->renderer); // render sok_ctx_walk(draw_ctx->ctx, &DRAW_CBS, draw_ctx); + // render text + draw_level_text(draw_ctx); + draw_moves_text(draw_ctx); + // flip SDL_RenderPresent(draw_ctx->renderer); } diff --git a/src/sdl/draw.h b/src/sdl/draw.h index 873287a..b8aeed4 100644 --- a/src/sdl/draw.h +++ b/src/sdl/draw.h @@ -3,6 +3,7 @@ #include // size_t #include +#include #include "../libsok/sok.h" #include "../text/levels.h" @@ -12,6 +13,7 @@ typedef struct { SDL_Renderer * const renderer; SDL_Texture *sprites[MAX_SPRITES]; + TTF_Font *font; const sok_ctx_t * const ctx; const size_t * const level_num; diff --git a/src/sdl/main.c b/src/sdl/main.c index 9341f4a..5eca49c 100644 --- a/src/sdl/main.c +++ b/src/sdl/main.c @@ -94,11 +94,40 @@ solve_on_error( die("Error solving level: %s", err); } +static void +set_level( + SDL_Window * const win, + draw_ctx_t * const draw_ctx, + sok_ctx_t * const ctx, + const size_t level_num +) { + // get level data + draw_ctx->level = levels_get_level(level_num); + + // load level + if (!sok_ctx_set_level(ctx, draw_ctx->level->data)) { + die("Couldn't load level %zu", level_num); + } + + // build title + char buf[1024]; + snprintf( + buf, sizeof(buf), + "Sokoban: %s: %s (#%zu)", + draw_ctx->level->pack, + draw_ctx->level->name, + level_num + ); + + // set window title + SDL_SetWindowTitle(win, buf); +} + int main(int argc, char *argv[]) { size_t level_num = (argc > 1) ? atoi(argv[1]) : 0, zoom = 0; - const level_t *level = levels_get_level(level_num); const char *sprites_png_path = "../assets/sprites.png"; + const char *font_path = "../assets/roboto.ttf"; // init warp buffer warp_buf_t warp_buf; @@ -108,10 +137,6 @@ int main(int argc, char *argv[]) { sok_ctx_t ctx; sok_ctx_init(&ctx, NULL); - if (!sok_ctx_set_level(&ctx, level->data)) { - die("Couldn't load level %zu", level_num); - } - // init sdl if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) { die("SDL_Init(): %s", SDL_GetError()); @@ -119,7 +144,18 @@ int main(int argc, char *argv[]) { // register exit handler if (atexit(SDL_Quit)) { - die("atexit(): %s", strerror(errno)); + die("atexit(SDL_Init): %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + // init SDL_TTF + if (TTF_Init()) { + die("TTF_Init(): %s", TTF_GetError()); + } + + // register exit handler + if (atexit(TTF_Quit)) { + die("atexit(TTF_Quit): %s", strerror(errno)); exit(EXIT_FAILURE); } @@ -135,15 +171,23 @@ int main(int argc, char *argv[]) { // init draw context draw_ctx_t draw_ctx = { .level_num = &level_num, - .level = level, .ctx = &ctx, .renderer = renderer, .zoom = &zoom, }; + // set level + set_level(win, &draw_ctx, &ctx, level_num); + // init sprites sprites_init(renderer, sprites_png_path, draw_ctx.sprites); + // load font + draw_ctx.font = TTF_OpenFontIndex(font_path, 16, 0); + if (!draw_ctx.font) { + die("TTF_OpenFontIndex(): %s", TTF_GetError()); + } + bool done = false; SDL_Event ev; while (!done) { @@ -176,13 +220,9 @@ int main(int argc, char *argv[]) { if (sok_ctx_is_done(&ctx)) { // advance level level_num++; - level = levels_get_level(level_num); - draw_ctx.level = level; - // load next level - if (!sok_ctx_set_level(&ctx, level->data)) { - die("Couldn't load level %zu", level_num); - } + // set level + set_level(win, &draw_ctx, &ctx, level_num); } else { warn("cannot advance to next level"); } @@ -190,20 +230,15 @@ int main(int argc, char *argv[]) { break; case ACTION_RESET: // reset level - if (!sok_ctx_set_level(&ctx, level->data)) { + if (!sok_ctx_set_level(&ctx, draw_ctx.level->data)) { die("Couldn't load level %zu", level_num); } break; case ACTION_WARP: if (warp_buf_get(&warp_buf, &level_num)) { - level = levels_get_level(level_num); - draw_ctx.level = level; - // load level - if (!sok_ctx_set_level(&ctx, level->data)) { - die("Couldn't load level %zu", level_num); - } + set_level(win, &draw_ctx, &ctx, level_num); // clear warp buf warp_buf_clear(&warp_buf); -- cgit v1.2.3