lav-sdl

SDL верзија програма Лавиринт
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување 869d8ea6524320f79e27eb299291384219873692
родитељ ee42f2d95461b4871d7d7995707b590a4e41aa83
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Tue, 15 Aug 2023 06:38:11 +0200

Sort functions, tidy up source, add copyright line to source

Signed-off-by: Страхиња Радић <contact@strahinja.org>

Diffstat:
M.gitignore | 1+
Mlav-sdl.c | 642++++++++++++++++++++++++++++++++++++++++++-------------------------------------
измењених датотека: 2, додавања: 343(+), брисања: 300(-)

diff --git a/.gitignore b/.gitignore @@ -11,6 +11,7 @@ *.pdf *.ps *.swp +*.tmp *.did nohup.out *.gz diff --git a/lav-sdl.c b/lav-sdl.c @@ -1,5 +1,5 @@ /* This program is licensed under the terms of GNU GPL v3 or (at your option) - * any later version. + * any later version. Copyright (C) 2023 Strahinya Radich. * See the file LICENSE for exact copyright and license details. */ #define _POSIX_C_SOURCE 200809L @@ -13,34 +13,46 @@ #include <SDL.h> #include <SDL_image.h> -#define PROGNAME "lav-sdl" +#define ANIM_STEPS 10 +#define ANIM_DELAY 10 +#define CELL_SIZE 32 #define DEFAULT_WIDTH 800 #define DEFAULT_HEIGHT 600 -#define WIN_TITLE "Lavirint (SDL version)" -#define CELL_SIZE 32 -#define LABYRINTH_MAXWIDTH 40 #define LABYRINTH_MAXHEIGHT 20 +#define LABYRINTH_MAXWIDTH 40 #define LOCATION_STACK_MAX (LABYRINTH_MAXWIDTH * LABYRINTH_MAXHEIGHT) +#define PRINT_BUFSIZE 4096 +#define PROGNAME "lav-sdl" #define SEARCHING_DELAY 10 -#define ANIM_STEPS 10 -#define ANIM_DELAY 1 -#define TER16_WIDTH 8 #define TER16_HEIGHT 17 +#define TER16_WIDTH 8 +#define WIN_TITLE "Lavirint (SDL version)" -#define EPS 1e-15 #define MIN(a, b) (((a) < (b)) ? (a) : (b)) -enum { CELL_EMPTY, CELL_WALL, CELL_FAIL, CELL_OK, CELL_HERO }; -enum { STATE_SEARCHING, STATE_SEARCHING_PAUSED, STATE_FAILURE, STATE_SUCCESS }; +/* clang-format off */ +enum { + CELL_EMPTY, + CELL_WALL, + CELL_FAIL, + CELL_OK, + CELL_HERO +}; -const char* state_descriptions[] = {"Searching for exit", - "Searching (paused)", "Failed!", "Success!"}; +enum { + STATE_SEARCHING, + STATE_SEARCHING_PAUSED, + STATE_FAILURE, + STATE_SUCCESS +}; -struct Labyrinth { - char** cells; - int width; - int height; +const char* state_descriptions[] = { + "Searching for exit", + "Searching (paused)", + "Failed!", + "Success!" }; +/* clang-format on */ struct AnimationState { SDL_FPoint position; @@ -51,24 +63,55 @@ struct AnimationState { int final_step; }; -static int running = 1; +struct Labyrinth { + char** cells; + int width; + int height; +}; + +static struct AnimationState animation; +static SDL_Point hero, start, end; +static struct Labyrinth labyrinth; +static int location_pointer = 0; +static SDL_Point* location_stack = NULL; static int redraw = 1; -static int state = STATE_SEARCHING_PAUSED; +static SDL_Renderer* renderer = NULL; +static int running = 1; +static float scale_factor = 1.0f; static int screen_width = DEFAULT_WIDTH; static int screen_height = DEFAULT_HEIGHT; -static float scale_factor = 1.0f; -static SDL_Window* window = NULL; -static SDL_Renderer* renderer = NULL; static SDL_Texture* sprites = NULL; +static int state = STATE_SEARCHING_PAUSED; static SDL_Texture* ter16_texture = NULL; -static struct Labyrinth labyrinth; -static SDL_Point hero, start, end; -static SDL_Point* location_stack = NULL; -static int location_pointer = 0; -static struct AnimationState animation; +static SDL_Window* window = NULL; -#define PRINT_BUFSIZE 4096 -#define LOAD_BUFSIZE 4096 +void print_debug(const char* fmt, ...); +void print_error(const char* fmt, ...); +void assign_point(const SDL_Point* from, SDL_Point* to); +void assign_point_xy(const int x, const int y, SDL_Point* to); +void assign_pointF(const SDL_FPoint* from, SDL_FPoint* to); +void assign_point_xyF(const float x, const float y, SDL_FPoint* to); +void assign_pointIF(const SDL_Point* from, SDL_FPoint* to); +void assign_point_xyIF(const int x, const int y, SDL_FPoint* to); +void calculate_delta(void); +void cleanup(void); +void draw(void); +void draw_text(const int x, const int y, const int font_width, + const int font_height, SDL_Texture* font_tex, const char* text, ...); +void get_sprite_xy(const char cell, int* x, int* y); +void handle_event(SDL_Event* event); +void labyrinth_coord_to_screen_coord(const int x, const int y, float* to_x, + float* to_y); +void labyrinth_coord_to_screen_coordF(const float x, const float y, float* to_x, + float* to_y); +void load_textures(void); +void load_labyrinth(const char* pathname); +int location_pop(SDL_Point* location); +void location_push(const SDL_Point* location); +void next_step(void); +int passable(const int x, const int y); +void reset(void); +void update_size(void); void print_debug(const char* fmt, ...) @@ -95,6 +138,63 @@ print_error(const char* fmt, ...) } void +assign_point(const SDL_Point* from, SDL_Point* to) +{ + to->x = from->x; + to->y = from->y; +} + +void +assign_point_xy(const int x, const int y, SDL_Point* to) +{ + to->x = x; + to->y = y; +} + +void +assign_pointF(const SDL_FPoint* from, SDL_FPoint* to) +{ + to->x = from->x; + to->y = from->y; +} + +void +assign_point_xyF(const float x, const float y, SDL_FPoint* to) +{ + to->x = x; + to->y = y; +} + +void +assign_pointIF(const SDL_Point* from, SDL_FPoint* to) +{ + to->x = (float)from->x; + to->y = (float)from->y; +} + +void +assign_point_xyIF(const int x, const int y, SDL_FPoint* to) +{ + to->x = (float)x; + to->y = (float)y; +} + +void +calculate_delta(void) +{ + animation.delta.x + = fabsf(animation.destination.x - animation.position.x) + / ANIM_STEPS; + if (animation.destination.x < animation.position.x) + animation.delta.x *= -1; + animation.delta.y + = fabsf(animation.destination.y - animation.position.y) + / ANIM_STEPS; + if (animation.destination.y < animation.position.y) + animation.delta.y *= -1; +} + +void cleanup(void) { free(location_stack); @@ -115,6 +215,88 @@ cleanup(void) } void +draw(void) +{ + SDL_Rect bg_rect, cell_rect; + SDL_FRect dest_rect; + int x, y; + int cx = screen_width / 2, cy = screen_height / 2; + + SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); + SDL_RenderClear(renderer); + + bg_rect.x = cx - labyrinth.width / 2 * CELL_SIZE * scale_factor; + bg_rect.y = cy - labyrinth.height / 2 * CELL_SIZE * scale_factor; + bg_rect.w = CELL_SIZE * scale_factor * labyrinth.width; + bg_rect.h = CELL_SIZE * scale_factor * labyrinth.height; + SDL_SetRenderDrawColor(renderer, 0x22, 0x22, 0x22, SDL_ALPHA_OPAQUE); + SDL_RenderFillRect(renderer, &bg_rect); + + cell_rect.w = CELL_SIZE; + cell_rect.h = CELL_SIZE; + + dest_rect.w = CELL_SIZE * scale_factor; + dest_rect.h = CELL_SIZE * scale_factor; + + for (y = 0; y < labyrinth.height; y++) + for (x = 0; x < labyrinth.width; x++) + { + if (x == start.x && y == start.y + && (animation.active || hero.x != x + || hero.y != y)) + { + cell_rect.x = 1 + 8 * (CELL_SIZE + 1); + cell_rect.y = 1; + } + else if (x == end.x && y == end.y + && (animation.active || hero.x != x + || hero.y != y)) + { + cell_rect.x = 1 + 7 * (CELL_SIZE + 1); + cell_rect.y = 1; + } + else if (animation.active + && labyrinth.cells[y][x] == CELL_HERO) + get_sprite_xy(CELL_EMPTY, &cell_rect.x, + &cell_rect.y); + else + get_sprite_xy(labyrinth.cells[y][x], + &cell_rect.x, &cell_rect.y); + labyrinth_coord_to_screen_coord(x, y, &dest_rect.x, + &dest_rect.y); + SDL_RenderCopyF(renderer, sprites, &cell_rect, + &dest_rect); + } + + draw_text(bg_rect.x, bg_rect.y + bg_rect.h, TER16_WIDTH, TER16_HEIGHT, + ter16_texture, "Column: %2d, Row: %2d", hero.x + 1, + hero.y + 1); + draw_text(cx, bg_rect.y + bg_rect.h, TER16_WIDTH, TER16_HEIGHT, + ter16_texture, "Status: %s", state_descriptions[state]); + + if (animation.active) + { + labyrinth_coord_to_screen_coordF(animation.position.x, + animation.position.y, &dest_rect.x, &dest_rect.y); + get_sprite_xy((const char)CELL_HERO, &cell_rect.x, &cell_rect.y); + SDL_RenderCopyF(renderer, sprites, &cell_rect, &dest_rect); + animation.position.x += animation.delta.x; + animation.position.y += animation.delta.y; + animation.step++; + if (animation.step == animation.final_step) + { + animation.active = 0; + hero.x = (int)animation.destination.x; + hero.y = (int)animation.destination.y; + labyrinth.cells[hero.y][hero.x] = CELL_HERO; + } + } + + SDL_RenderPresent(renderer); + // SDL_RenderFlush(renderer); +} + +void draw_text(const int x, const int y, const int font_width, const int font_height, SDL_Texture* font_tex, const char* text, ...) { @@ -179,27 +361,99 @@ draw_text(const int x, const int y, const int font_width, const int font_height, } void -update_size(void) +get_sprite_xy(const char cell, int* x, int* y) { - SDL_GetWindowSize(window, &screen_width, &screen_height); - scale_factor = MIN((float)screen_width / DEFAULT_WIDTH, - (float)screen_height / DEFAULT_HEIGHT); + switch (cell) + { + case CELL_WALL: + *x = 1; + *y = 1; + break; + case CELL_FAIL: + *x = 1 + 1 * (CELL_SIZE + 1); + *y = 1; + break; + case CELL_OK: + *x = 1 + 2 * (CELL_SIZE + 1); + *y = 1; + break; + case CELL_HERO: + switch (state) + { + case STATE_SUCCESS: + *x = 1 + 4 * (CELL_SIZE + 1); + *y = 1; + break; + case STATE_FAILURE: + *x = 1 + 6 * (CELL_SIZE + 1); + *y = 1; + break; + default: + *x = 1 + 3 * (CELL_SIZE + 1); + *y = 1; + break; + } + break; + default: + *x = 1 + 5 * (CELL_SIZE + 1); + *y = 1; + } } void -labyrinth_coord_to_screen_coord(const int x, const int y, float* to_x, - float* to_y) +handle_event(SDL_Event* event) { - int cx = screen_width / 2, cy = screen_height / 2; + SDL_Keysym keysym; - *to_x = cx - labyrinth.width / 2 * CELL_SIZE * scale_factor - + x * CELL_SIZE * scale_factor; - *to_y = cy - labyrinth.height / 2 * CELL_SIZE * scale_factor - + y * CELL_SIZE * scale_factor; + if (!event) + return; + switch (event->type) + { + case SDL_WINDOWEVENT: + switch (event->window.event) + { + case SDL_WINDOWEVENT_RESIZED: + update_size(); + print_debug("Got Resized, size: %d x %d, scale = %2.2f", + screen_width, screen_height, scale_factor); + redraw = 1; + break; + } + break; + case SDL_KEYDOWN: + keysym = event->key.keysym; + + /*print_debug("Got Keydown, sym = %X, mod = %X", + keysym.sym, keysym.mod);*/ + + if (keysym.sym == SDLK_ESCAPE) + running = 0; + else if (keysym.sym == SDLK_SPACE) + { + if (state == STATE_SEARCHING) + { + print_debug("State: paused"); + state = STATE_SEARCHING_PAUSED; + } + else if (state == STATE_SEARCHING_PAUSED) + { + print_debug("State: searching"); + state = STATE_SEARCHING; + } + else + { + print_debug("Resetting"); + reset(); + } + } + else if (keysym.sym == SDLK_q && (keysym.mod & KMOD_CTRL)) + running = 0; + break; + } } void -labyrinth_coord_to_screen_coordF(const float x, const float y, float* to_x, +labyrinth_coord_to_screen_coord(const int x, const int y, float* to_x, float* to_y) { int cx = screen_width / 2, cy = screen_height / 2; @@ -211,60 +465,15 @@ labyrinth_coord_to_screen_coordF(const float x, const float y, float* to_x, } void -assign_point(const SDL_Point* from, SDL_Point* to) -{ - to->x = from->x; - to->y = from->y; -} - -void -assign_point_xy(const int x, const int y, SDL_Point* to) -{ - to->x = x; - to->y = y; -} - -void -assign_pointF(const SDL_FPoint* from, SDL_FPoint* to) -{ - to->x = from->x; - to->y = from->y; -} - -void -assign_point_xyF(const float x, const float y, SDL_FPoint* to) -{ - to->x = x; - to->y = y; -} - -void -assign_pointIF(const SDL_Point* from, SDL_FPoint* to) -{ - to->x = (float)from->x; - to->y = (float)from->y; -} - -void -assign_point_xyIF(const int x, const int y, SDL_FPoint* to) -{ - to->x = (float)x; - to->y = (float)y; -} - -void -calculate_delta(void) +labyrinth_coord_to_screen_coordF(const float x, const float y, float* to_x, + float* to_y) { - animation.delta.x - = fabsf(animation.destination.x - animation.position.x) - / ANIM_STEPS; - if (animation.destination.x < animation.position.x) - animation.delta.x *= -1; - animation.delta.y - = fabsf(animation.destination.y - animation.position.y) - / ANIM_STEPS; - if (animation.destination.y < animation.position.y) - animation.delta.y *= -1; + int cx = screen_width / 2, cy = screen_height / 2; + + *to_x = cx - labyrinth.width / 2 * CELL_SIZE * scale_factor + + x * CELL_SIZE * scale_factor; + *to_y = cy - labyrinth.height / 2 * CELL_SIZE * scale_factor + + y * CELL_SIZE * scale_factor; } void @@ -404,203 +613,15 @@ load_labyrinth(const char* pathname) fclose(input); } -void -reset() -{ - for (int y = 0; y < labyrinth.height; y++) - for (int x = 0; x < labyrinth.width; x++) - if (labyrinth.cells[y][x] == CELL_FAIL - || labyrinth.cells[y][x] == CELL_OK - || labyrinth.cells[y][x] == CELL_HERO) - labyrinth.cells[y][x] = CELL_EMPTY; - hero.x = start.x; - hero.y = start.y; - labyrinth.cells[hero.y][hero.x] = CELL_HERO; - state = STATE_SEARCHING_PAUSED; - location_pointer = 0; - redraw = 1; -} - -void -get_sprite_xy(const char cell, int* x, int* y) -{ - switch (cell) - { - case CELL_WALL: - *x = 1; - *y = 1; - break; - case CELL_FAIL: - *x = 1 + 1 * (CELL_SIZE + 1); - *y = 1; - break; - case CELL_OK: - *x = 1 + 2 * (CELL_SIZE + 1); - *y = 1; - break; - case CELL_HERO: - switch (state) - { - case STATE_SUCCESS: - *x = 1 + 4 * (CELL_SIZE + 1); - *y = 1; - break; - case STATE_FAILURE: - *x = 1 + 6 * (CELL_SIZE + 1); - *y = 1; - break; - default: - *x = 1 + 3 * (CELL_SIZE + 1); - *y = 1; - break; - } - break; - default: - *x = 1 + 5 * (CELL_SIZE + 1); - *y = 1; - } -} - -void -draw(void) -{ - SDL_Rect bg_rect, cell_rect; - SDL_FRect dest_rect; - int x, y; - int cx = screen_width / 2, cy = screen_height / 2; - - SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); - SDL_RenderClear(renderer); - - bg_rect.x = cx - labyrinth.width / 2 * CELL_SIZE * scale_factor; - bg_rect.y = cy - labyrinth.height / 2 * CELL_SIZE * scale_factor; - bg_rect.w = CELL_SIZE * scale_factor * labyrinth.width; - bg_rect.h = CELL_SIZE * scale_factor * labyrinth.height; - SDL_SetRenderDrawColor(renderer, 0x22, 0x22, 0x22, SDL_ALPHA_OPAQUE); - SDL_RenderFillRect(renderer, &bg_rect); - - cell_rect.w = CELL_SIZE; - cell_rect.h = CELL_SIZE; - - dest_rect.w = CELL_SIZE * scale_factor; - dest_rect.h = CELL_SIZE * scale_factor; - - for (y = 0; y < labyrinth.height; y++) - for (x = 0; x < labyrinth.width; x++) - { - if (x == start.x && y == start.y - && (animation.active || hero.x != x - || hero.y != y)) - { - cell_rect.x = 1 + 8 * (CELL_SIZE + 1); - cell_rect.y = 1; - } - else if (x == end.x && y == end.y - && (animation.active || hero.x != x - || hero.y != y)) - { - cell_rect.x = 1 + 7 * (CELL_SIZE + 1); - cell_rect.y = 1; - } - else if (animation.active - && labyrinth.cells[y][x] == CELL_HERO) - get_sprite_xy(CELL_EMPTY, &cell_rect.x, - &cell_rect.y); - else - get_sprite_xy(labyrinth.cells[y][x], - &cell_rect.x, &cell_rect.y); - labyrinth_coord_to_screen_coord(x, y, &dest_rect.x, - &dest_rect.y); - SDL_RenderCopyF(renderer, sprites, &cell_rect, - &dest_rect); - } - - draw_text(bg_rect.x, bg_rect.y + bg_rect.h, TER16_WIDTH, TER16_HEIGHT, - ter16_texture, "Column: %2d, Row: %2d", hero.x + 1, - hero.y + 1); - draw_text(cx, bg_rect.y + bg_rect.h, - TER16_WIDTH, TER16_HEIGHT, ter16_texture, "Status: %s", - state_descriptions[state]); - - if (animation.active) - { - labyrinth_coord_to_screen_coordF(animation.position.x, - animation.position.y, &dest_rect.x, &dest_rect.y); - get_sprite_xy((const char)CELL_HERO, &cell_rect.x, &cell_rect.y); - SDL_RenderCopyF(renderer, sprites, &cell_rect, &dest_rect); - animation.position.x += animation.delta.x; - animation.position.y += animation.delta.y; - animation.step++; - if (animation.step == animation.final_step) - { - animation.active = 0; - hero.x = (int)animation.destination.x; - hero.y = (int)animation.destination.y; - labyrinth.cells[hero.y][hero.x] = CELL_HERO; - } - } - - SDL_RenderPresent(renderer); - // SDL_RenderFlush(renderer); -} - -void -handle_event(SDL_Event* event) -{ - SDL_Keysym keysym; - - if (!event) - return; - switch (event->type) - { - case SDL_WINDOWEVENT: - switch (event->window.event) - { - case SDL_WINDOWEVENT_RESIZED: - update_size(); - print_debug("Got Resized, size: %d x %d, scale = %2.2f", - screen_width, screen_height, scale_factor); - redraw = 1; - break; - } - break; - case SDL_KEYDOWN: - keysym = event->key.keysym; - - /*print_debug("Got Keydown, sym = %X, mod = %X", - keysym.sym, keysym.mod);*/ - - if (keysym.sym == SDLK_ESCAPE) - running = 0; - else if (keysym.sym == SDLK_SPACE) - { - if (state == STATE_SEARCHING) - { - print_debug("State: paused"); - state = STATE_SEARCHING_PAUSED; - } - else if (state == STATE_SEARCHING_PAUSED) - { - print_debug("State: searching"); - state = STATE_SEARCHING; - } - else - { - print_debug("Resetting"); - reset(); - } - } - else if (keysym.sym == SDLK_q && (keysym.mod & KMOD_CTRL)) - running = 0; - break; - } -} - int -passable(const int x, const int y) +location_pop(SDL_Point* location) { - return (x >= 0 && x < labyrinth.width && y >= 0 && y < labyrinth.height - && labyrinth.cells[y][x] == CELL_EMPTY); + if (location_pointer == 0) + return 1; + location_pointer--; + location->x = location_stack[location_pointer].x; + location->y = location_stack[location_pointer].y; + return 0; } void @@ -611,17 +632,6 @@ location_push(const SDL_Point* location) location_pointer++; } -int -location_pop(SDL_Point* location) -{ - if (location_pointer == 0) - return 1; - location_pointer--; - location->x = location_stack[location_pointer].x; - location->y = location_stack[location_pointer].y; - return 0; -} - void next_step(void) { @@ -717,6 +727,38 @@ next_step(void) } int +passable(const int x, const int y) +{ + return (x >= 0 && x < labyrinth.width && y >= 0 && y < labyrinth.height + && labyrinth.cells[y][x] == CELL_EMPTY); +} + +void +reset(void) +{ + for (int y = 0; y < labyrinth.height; y++) + for (int x = 0; x < labyrinth.width; x++) + if (labyrinth.cells[y][x] == CELL_FAIL + || labyrinth.cells[y][x] == CELL_OK + || labyrinth.cells[y][x] == CELL_HERO) + labyrinth.cells[y][x] = CELL_EMPTY; + hero.x = start.x; + hero.y = start.y; + labyrinth.cells[hero.y][hero.x] = CELL_HERO; + state = STATE_SEARCHING_PAUSED; + location_pointer = 0; + redraw = 1; +} + +void +update_size(void) +{ + SDL_GetWindowSize(window, &screen_width, &screen_height); + scale_factor = MIN((float)screen_width / DEFAULT_WIDTH, + (float)screen_height / DEFAULT_HEIGHT); +} + +int main(void) { SDL_Event event;