чување 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 | + |
| M | lav-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;