diff options
Diffstat (limited to 'src/sdl/main.c')
-rw-r--r-- | src/sdl/main.c | 335 |
1 files changed, 114 insertions, 221 deletions
diff --git a/src/sdl/main.c b/src/sdl/main.c index 831d3f7..882eefb 100644 --- a/src/sdl/main.c +++ b/src/sdl/main.c @@ -6,171 +6,47 @@ #include <SDL_image.h> #include "../text/levels.h" #include "../libsok/sok.h" +#include "util.h" #include "action.h" - -#define warn(...) do { \ - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__); \ -} while (0) - -#define die(...) do { \ - SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__); \ - exit(EXIT_FAILURE); \ -} while (0) - -static void -solve_on_error( - const char * const err -) { - die("Error solving level: %s", err); -} +#include "warp-buf.h" +#include "draw.h" static void draw_moves( const sok_ctx_t * const ctx, const size_t skip_moves ) { - printf("Solution (%zu moves): ", ctx->num_moves - skip_moves); + char buf[1024] = { 0 }; + size_t ofs = 0; + for (size_t i = skip_moves; i < ctx->num_moves; i++) { if (ctx->moves[i].dir >= SOK_DIR_LAST) { die("invalid move: %u", ctx->moves[i].dir); } - fputs(SOK_DIR_TO_STR(ctx->moves[i].dir), stdout); - } - printf("\n"); -} - -static const SDL_Color -RED = { .r = 0x00, .g = 0xFF, .b = 0x00, .a = 0xFF }, -BLACK = { .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF }; - -static SDL_Color -get_bg( - const sok_ctx_t * const ctx -) { - return (sok_ctx_is_done(ctx)) ? RED : BLACK; -} - -bool draw_on_wall( - const sok_ctx_t * const ctx, - const sok_pos_t pos, - void * const data -) { - SDL_Renderer *renderer = data; - SDL_Rect rect = { 32 * pos.x, 32 * pos.y, 32, 32 }; - - SDL_SetRenderDrawColor(renderer, 0x66, 0x66, 0x66, 0xFF); - - if (SDL_RenderFillRect(renderer, &rect)) { - die("SDL_RenderFillRect(): %s", SDL_GetError()); - } - - return true; -} - -bool draw_on_goal( - const sok_ctx_t * const ctx, - const sok_pos_t pos, - const bool has_player, - const bool has_box, - void * const data -) { - SDL_Renderer *renderer = data; - SDL_Rect rect = { 32 * pos.x, 32 * pos.y, 32, 32 }; - - SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF); - - if (SDL_RenderFillRect(renderer, &rect)) { - die("SDL_RenderFillRect(): %s", SDL_GetError()); - } - - return true; -} - -bool draw_on_home( - const sok_ctx_t * const ctx, - const sok_pos_t pos, - const bool has_goal, - void * const data -) { - SDL_Renderer *renderer = data; - SDL_Rect rect = { 32 * pos.x, 32 * pos.y, 32, 32 }; - - SDL_SetRenderDrawColor(renderer, 0xFF, has_goal ? 0xFF : 0x00, 0x00, 0xFF); - - if (SDL_RenderFillRect(renderer, &rect)) { - die("SDL_RenderFillRect(): %s", SDL_GetError()); - } - - return true; -} - -bool draw_on_box( - const sok_ctx_t * const ctx, - const sok_pos_t pos, - const bool has_goal, - void * const data -) { - SDL_Renderer *renderer = data; - SDL_Rect rect = { 32 * pos.x, 32 * pos.y, 32, 32 }; - - SDL_SetRenderDrawColor(renderer, 0x00, has_goal ? 0xFF : 0x00, 0xFF, 0xFF); - - if (SDL_RenderFillRect(renderer, &rect)) { - die("SDL_RenderFillRect(): %s", SDL_GetError()); + buf[ofs++] = SOK_DIR_TO_CHAR(ctx->moves[i].dir); } - return true; + SDL_Log("Solution (%zu moves): %s", ctx->num_moves - skip_moves, buf); } -static sok_ctx_walk_cbs_t -DRAW_CBS = { - .on_wall = draw_on_wall, - .on_goal = draw_on_goal, - .on_home = draw_on_home, - .on_box = draw_on_box, -}; -/* - * typedef struct { - * sok_ctx_walk_pos_cb_t on_size, - * on_wall; - * sok_ctx_walk_tile_cb_t on_home, - * on_box; - * sok_ctx_walk_goal_cb_t on_goal; - * sok_ctx_walk_move_cb_t on_move; - * } sok_ctx_walk_cbs_t; - * - * _Bool sok_ctx_walk( - * const sok_ctx_t * const, - * const sok_ctx_walk_cbs_t * const, - * void * const - * ); - */ - static void -draw( - SDL_Renderer * const renderer, - const sok_ctx_t * const ctx, - const size_t level_num, - const level_t * const level +solve_on_error( + const char * const err ) { - // clear - const SDL_Color c = get_bg(ctx); - SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, c.a); - SDL_RenderClear(renderer); - - sok_ctx_walk(ctx, &DRAW_CBS, renderer); - - // flip - SDL_RenderPresent(renderer); + die("Error solving level: %s", err); } int main(int argc, char *argv[]) { - size_t warp_buf = 0; - size_t level_num = (argc > 1) ? atoi(argv[1]) : 0; + size_t level_num = (argc > 1) ? atoi(argv[1]) : 0, + zoom = 0; const level_t *level = levels_get_level(level_num); - // init context + // init warp buffer + warp_buf_t warp_buf; + warp_buf_clear(&warp_buf); + + // init sok context sok_ctx_t ctx; sok_ctx_init(&ctx, NULL); @@ -195,102 +71,119 @@ int main(int argc, char *argv[]) { die("SDL_CreateWindowAndRenderer(): %s", SDL_GetError()); } + // init draw context + draw_ctx_t draw_ctx = { + .level_num = &level_num, + .level = level, + .ctx = &ctx, + .renderer = renderer, + .zoom = &zoom, + }; + bool done = false; SDL_Event ev; while (!done) { while (SDL_PollEvent(&ev)) { - switch (ev.type) { - case SDL_QUIT: + const action_t action = get_action(&ev); + + switch (action.type) { + case ACTION_NONE: + // do nothing + break; + case ACTION_QUIT: done = true; break; - case SDL_KEYUP: + case ACTION_MOVE: + if (!sok_ctx_move(&ctx, (sok_dir_t) action.data)) { + warn("move %s failed", SOK_DIR_TO_STR((sok_dir_t) action.data)); + } + + break; + case ACTION_UNDO: + if (!sok_ctx_undo(&ctx)) { + warn("undo failed"); + } + + break; + case ACTION_NEXT: + 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); + } + } else { + warn("cannot advance to next level"); + } + + break; + case ACTION_RESET: + // reset level + if (!sok_ctx_set_level(&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); + } + + // clear warp buf + warp_buf_clear(&warp_buf); + } + + break; + case ACTION_WARP_BUF_PUSH: + warp_buf_push_num(&warp_buf, action.data); + + break; + case ACTION_WARP_BUF_POP: + warp_buf_pop_num(&warp_buf); + + break; + case ACTION_SOLVE: { - const action_t action = get_action(ev.key.keysym.sym); - - switch (action.type) { - case ACTION_QUIT: - done = true; - break; - case ACTION_MOVE: - if (!sok_ctx_move(&ctx, (sok_dir_t) action.data)) { - warn("move %s failed", SOK_DIR_TO_STR((sok_dir_t) action.data)); - } - - break; - case ACTION_UNDO: - if (!sok_ctx_undo(&ctx)) { - warn("undo failed"); - } - - break; - case ACTION_NEXT: - if (sok_ctx_is_done(&ctx)) { - // advance level - level_num++; - level = levels_get_level(level_num); - - // load next level - if (!sok_ctx_set_level(&ctx, level->data)) { - die("Couldn't load level %zu", level_num); - } - } else { - warn("cannot advance to next level"); - } - - break; - case ACTION_RESET: - // reset level - if (!sok_ctx_set_level(&ctx, level->data)) { - die("Couldn't load level %zu", level_num); - } - - break; - case ACTION_WARP: - level_num = warp_buf; - level = levels_get_level(level_num); - - // load level - if (!sok_ctx_set_level(&ctx, level->data)) { - die("Couldn't load level %zu", level_num); - } - - warp_buf = 0; - - break; - case ACTION_WARP_BUF_PUSH: - warp_buf = 10 * warp_buf + action.data; - - break; - case ACTION_WARP_BUF_POP: - warp_buf /= 10; - - break; - case ACTION_SOLVE: - { - // get current number of moves - const size_t old_num_moves = ctx.num_moves; - - if (sok_solve(&ctx, solve_on_error)) { - // found solution, print it - draw_moves(&ctx, old_num_moves); - } else { - warn("Couldn't solve level"); - } - } - default: - // ignore - break; + // get current number of moves + const size_t old_num_moves = ctx.num_moves; + + if (sok_solve(&ctx, solve_on_error)) { + // found solution, print it + draw_moves(&ctx, old_num_moves); + } else { + warn("Couldn't solve level"); } } break; + case ACTION_ZOOM_IN: + if (zoom < 10) { + zoom++; + } + + break; + case ACTION_ZOOM_OUT: + if (zoom > 0) { + zoom--; + } + + break; default: // ignore break; } } - draw(renderer, &ctx, level_num, level); + draw(&draw_ctx); } // fini renderer, window |