#include // bool #include "util.h" // warn()/die() #include "color.h" // set_color() #include "draw.h" static size_t get_cell_size( const draw_ctx_t * const draw_ctx ) { return 32 + 8 * *draw_ctx->zoom; } static SDL_Rect get_cell_rect( const draw_ctx_t * const draw_ctx, const sok_pos_t pos ) { const size_t cell_size = get_cell_size(draw_ctx); return (SDL_Rect) { draw_ctx->render_ofs.x + pos.x * cell_size, draw_ctx->render_ofs.y + pos.y * cell_size, cell_size, cell_size }; } static bool draw_on_size( const sok_ctx_t * const ctx, const sok_pos_t level_size, void * const data ) { draw_ctx_t * const draw_ctx = data; const size_t cell_size = get_cell_size(draw_ctx); // get renderer size int renderer_x, renderer_y; if (SDL_GetRendererOutputSize(draw_ctx->renderer, &renderer_x, &renderer_y)) { die("SDL_GetRendererOutputSize(): %s", SDL_GetError()); } // calculate renderer offset draw_ctx->render_ofs.x = (renderer_x - level_size.x * cell_size) / 2; draw_ctx->render_ofs.y = (renderer_y - level_size.y * cell_size) / 2; return true; } static bool draw_on_walls_start( const sok_ctx_t * const ctx, void * const data ) { draw_ctx_t * const draw_ctx = data; set_color(draw_ctx->renderer, COLOR_WALL); return true; } static bool draw_on_wall( const sok_ctx_t * const ctx, const sok_pos_t pos, void * const data ) { draw_ctx_t * const draw_ctx = data; const SDL_Rect rect = get_cell_rect(draw_ctx, pos); if (SDL_RenderFillRect(draw_ctx->renderer, &rect)) { die("SDL_RenderFillRect(): %s", SDL_GetError()); } return true; } static bool draw_on_goals_start( const sok_ctx_t * const ctx, void * const data ) { draw_ctx_t * const draw_ctx = data; set_color(draw_ctx->renderer, COLOR_GOAL); return true; } static 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 ) { draw_ctx_t * const draw_ctx = data; const SDL_Rect rect = get_cell_rect(draw_ctx, pos); if (SDL_RenderFillRect(draw_ctx->renderer, &rect)) { die("SDL_RenderFillRect(): %s", SDL_GetError()); } return true; } static bool draw_on_home( const sok_ctx_t * const ctx, const sok_pos_t pos, const bool has_goal, void * const data ) { draw_ctx_t * const draw_ctx = data; const SDL_Rect rect = get_cell_rect(draw_ctx, pos); set_color(draw_ctx->renderer, has_goal ? COLOR_HOME_GOAL : COLOR_HOME); if (SDL_RenderFillRect(draw_ctx->renderer, &rect)) { die("SDL_RenderFillRect(): %s", SDL_GetError()); } return true; } static bool draw_on_box( const sok_ctx_t * const ctx, const sok_pos_t pos, const bool has_goal, void * const data ) { draw_ctx_t * const draw_ctx = data; const SDL_Rect rect = get_cell_rect(draw_ctx, pos); set_color(draw_ctx->renderer, has_goal ? COLOR_BOX_GOAL : COLOR_BOX); if (SDL_RenderFillRect(draw_ctx->renderer, &rect)) { die("SDL_RenderFillRect(): %s", SDL_GetError()); } return true; } static const sok_ctx_walk_cbs_t DRAW_CBS = { .on_size = draw_on_size, .on_walls_start = draw_on_walls_start, .on_wall = draw_on_wall, .on_goals_start = draw_on_goals_start, .on_goal = draw_on_goal, .on_home = draw_on_home, .on_box = draw_on_box, }; void draw( draw_ctx_t * const draw_ctx ) { // 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); // flip SDL_RenderPresent(draw_ctx->renderer); }