aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/roboto.ttfbin0 -> 171676 bytes
-rw-r--r--meson.build1
-rw-r--r--src/sdl/color.c2
-rw-r--r--src/sdl/draw.c140
-rw-r--r--src/sdl/draw.h2
-rw-r--r--src/sdl/main.c75
6 files changed, 198 insertions, 22 deletions
diff --git a/assets/roboto.ttf b/assets/roboto.ttf
new file mode 100644
index 0000000..2c97eea
--- /dev/null
+++ b/assets/roboto.ttf
Binary files 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 <stdbool.h> // bool
+#include <math.h> // 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 <stddef.h> // size_t
#include <SDL.h>
+#include <SDL_ttf.h>
#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);