чување 0e6f8fa0369d055b2a39a3b084b1f669d49d86f2
родитељ b5de147b723c119ad1433058563ff7d5f699a907
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Mon, 14 Aug 2023 22:27:01 +0200
Add animations, sprites...
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
измењених датотека: 8, додавања: 695(+), брисања: 65(-)
diff --git a/README b/README
@@ -0,0 +1,33 @@
+Lavirint
+========
+
+SDL maze solver
+
+
+License
+-------
+
+lav-sdl - SDL maze solver
+Copyright (C) 2023 Strahinya Radich
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+---
+
+Sprite sheet ter16.png created in GIMP using Terminus font 4.49.1, Copyright (C)
+2020 Dimitar Toshkov Zhekov[1], licensed under SIL Open Font License 1.1. See
+file OFL.TXT for more information.
+
+
+[1]: http://terminus-font.sourceforge.net/
diff --git a/l00.dat b/l00.dat
@@ -0,0 +1,10 @@
+ 1 3
+ 16 8
+ 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0
+ 1 1 0 1 1 0 0 0 1 0 0 1 0 1 0 1
+ 0 1 0 1 0 1 0 1 0 0 1 0 0 1 1 1
+ 0 0 0 0 0 1 0 1 0 1 1 0 1 0 1 0
+ 1 1 0 1 1 0 0 0 0 1 0 0 1 0 1 0
+ 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0
+ 0 1 0 1 0 1 1 1 1 0 0 0 1 0 1 0
+ 0 0 0 1 0 0 0 0 1 0 1 0 0 0 1 0
diff --git a/l01.dat b/l01.dat
@@ -0,0 +1,13 @@
+1 1
+24 11
+0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0
+1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 0 1 0
+0 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 0 1 0 1 0 1 1 0
+0 1 1 1 0 1 0 1 0 1 0 1 0 1 1 0 1 1 0 1 0 0 1 0
+0 1 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 1 0 1 0
+0 1 0 1 1 1 1 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 0
+0 1 0 1 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0
+0 1 0 1 0 1 0 1 0 1 1 1 0 1 0 1 1 1 0 1 1 1 1 1
+0 1 0 0 0 1 0 1 0 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1
+0 1 1 1 0 1 0 1 1 1 0 1 0 1 0 1 0 1 1 1 0 1 0 1
+0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0
diff --git a/lav-sdl.c b/lav-sdl.c
@@ -6,15 +6,35 @@
#define _DEFAULT_SOURCE
#define _XOPEN_SOURCE
+#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
-
-#define PROGNAME "lav-sdl"
-#define DEFAULT_WIDTH 800
-#define DEFAULT_HEIGHT 600
-#define WIN_TITLE "Lavirint (SDL version)"
+#include <SDL_image.h>
+
+#define PROGNAME "lav-sdl"
+#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 LOCATION_STACK_MAX (LABYRINTH_MAXWIDTH * LABYRINTH_MAXHEIGHT)
+#define SEARCHING_DELAY 10
+#define ANIM_STEPS 10
+#define ANIM_DELAY 1
+#define TER16_WIDTH 8
+#define TER16_HEIGHT 17
+
+#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 };
+
+const char* state_descriptions[] = {"Searching for exit",
+ "Searching for exit (paused)", "Failed!", "Success!"};
struct Labyrinth {
char** cells;
@@ -22,18 +42,33 @@ struct Labyrinth {
int height;
};
-static int running = 1;
-static int redraw = 1;
-static int screen_width = DEFAULT_WIDTH;
-static int screen_height = DEFAULT_HEIGHT;
-static SDL_Window* window = NULL;
-static SDL_Renderer* renderer = NULL;
+struct AnimationState {
+ SDL_FPoint position;
+ SDL_FPoint destination;
+ SDL_FPoint delta;
+ int active;
+ int step;
+ int final_step;
+};
+
+static int running = 1;
+static int redraw = 1;
+static int state = STATE_SEARCHING_PAUSED;
+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 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;
#define PRINT_BUFSIZE 4096
-
-#define CELL_EMPTY 0
-#define CELL_WALL 1
+#define LOAD_BUFSIZE 4096
void
print_debug(const char* fmt, ...)
@@ -62,54 +97,449 @@ print_error(const char* fmt, ...)
void
cleanup(void)
{
- for (int y = 0; y < labyrinth.height; y++)
+ free(location_stack);
+
+ for (int y = 0; y < LABYRINTH_MAXHEIGHT; y++)
free(labyrinth.cells[y]);
free(labyrinth.cells);
+
+ if (ter16_texture)
+ SDL_DestroyTexture(ter16_texture);
+ if (sprites)
+ SDL_DestroyTexture(sprites);
+ if (renderer)
+ SDL_DestroyRenderer(renderer);
+ if (window)
+ SDL_DestroyWindow(window);
SDL_Quit();
}
void
+draw_text(const int x, const int y, const int font_width, const int font_height,
+ SDL_Texture* font_tex, const char* text, ...)
+{
+ char buf[PRINT_BUFSIZE];
+ va_list args;
+ const char* pbuf = NULL;
+ int xstart = 0;
+ int ystart = 0;
+ SDL_Rect source_rect;
+ SDL_FRect dest_rect;
+ int index = 0;
+ int chars_per_row = 0;
+ char first_char = ' ';
+ char last_char = '~';
+ int tex_w, tex_h;
+
+ if (!text || !font_tex)
+ return;
+
+ va_start(args, text);
+ vsnprintf(buf, sizeof(buf), text, args);
+ va_end(args);
+
+ source_rect.w = font_width;
+ source_rect.h = font_height;
+
+ dest_rect.x = x;
+ dest_rect.y = y;
+ dest_rect.w = font_width * scale_factor;
+ dest_rect.h = font_height * scale_factor;
+
+ if (SDL_QueryTexture(font_tex, NULL, NULL, &tex_w, &tex_h) < 0)
+ {
+ print_error("SDL_QueryTexture failed: %s", SDL_GetError());
+ exit(1);
+ }
+
+ chars_per_row = tex_w / (font_width + 1);
+
+ pbuf = buf;
+ while (*pbuf)
+ {
+ if (*pbuf >= first_char && *pbuf <= last_char)
+ {
+ index = (int)(*pbuf - first_char);
+
+ xstart = 1 + index % chars_per_row * (font_width + 1);
+ ystart = 1 + index / chars_per_row * (font_height + 1);
+ }
+ else
+ break;
+
+ source_rect.x = xstart;
+ source_rect.y = ystart;
+
+ SDL_RenderCopyF(renderer, font_tex, &source_rect, &dest_rect);
+
+ dest_rect.x += font_width * scale_factor;
+
+ pbuf++;
+ }
+}
+
+void
update_size(void)
{
SDL_GetWindowSize(window, &screen_width, &screen_height);
+ scale_factor = MIN((float)screen_width / DEFAULT_WIDTH,
+ (float)screen_height / DEFAULT_HEIGHT);
+}
+
+void
+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;
+
+ *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
+labyrinth_coord_to_screen_coordF(const float x, const float y, float* to_x,
+ float* to_y)
+{
+ 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
+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
+load_textures(void)
+{
+ SDL_Surface* surface = NULL;
+
+ surface = IMG_Load("sprites.png");
+ if (!surface)
+ {
+ print_error("IMG_Load failed: %s", IMG_GetError());
+ exit(1);
+ }
+
+ sprites = SDL_CreateTextureFromSurface(renderer, surface);
+ if (!sprites)
+ {
+ print_error("SDL_CreateTextureFromSurface failed: %s",
+ SDL_GetError());
+ exit(1);
+ }
+ SDL_FreeSurface(surface);
+ surface = NULL;
+
+ surface = IMG_Load("ter16.png");
+ if (!surface)
+ {
+ print_error("IMG_Load failed: %s", IMG_GetError());
+ exit(1);
+ }
+
+ ter16_texture = SDL_CreateTextureFromSurface(renderer, surface);
+ if (!ter16_texture)
+ {
+ print_error("SDL_CreateTextureFromSurface failed: %s",
+ SDL_GetError());
+ exit(1);
+ }
+
+ SDL_FreeSurface(surface);
+}
+
+void
+load_labyrinth(const char* pathname)
+{
+ FILE* input = NULL;
+ int x, y;
+ int firstline = 1;
+
+ input = fopen(pathname, "rt");
+ if (!input)
+ {
+ print_error("load_labyrinth: fopen failed: %s (%s)",
+ strerror(errno), pathname);
+ exit(1);
+ }
+
+ labyrinth.cells = (char**)calloc(LABYRINTH_MAXHEIGHT, sizeof(char*));
+ if (!labyrinth.cells)
+ {
+ print_error("calloc failed");
+ exit(1);
+ }
+ for (y = 0; y < LABYRINTH_MAXHEIGHT; y++)
+ {
+ labyrinth.cells[y] = (char*)calloc(LABYRINTH_MAXWIDTH, 1);
+ if (!labyrinth.cells[y])
+ {
+ print_error("calloc failed");
+ exit(1);
+ }
+ }
+ fscanf(input, "%d %d\n", &start.x, &start.y);
+ /* 1-based coordinates for compatibility */
+ start.x--;
+ start.y--;
+ fscanf(input, "%d %d\n", &end.x, &end.y);
+ end.x--;
+ end.y--;
+
+ x = 0;
+ y = 0;
+ labyrinth.width = 0;
+ labyrinth.height = 0;
+ while (!feof(input))
+ {
+ char ch = fgetc(input);
+ if (ch == EOF)
+ continue;
+
+ if (ch == '1')
+ {
+ labyrinth.cells[y][x] = CELL_WALL;
+ x++;
+ if (firstline)
+ labyrinth.width++;
+ }
+ else if (ch == '0')
+ {
+ labyrinth.cells[y][x] = CELL_EMPTY;
+ x++;
+ if (firstline)
+ labyrinth.width++;
+ }
+ else if (ch == '\n')
+ {
+ x = 0;
+ y++;
+ firstline = 0;
+ labyrinth.height++;
+ }
+ else if (strchr(" \r", ch))
+ /* Ignore CR for compatibility */;
+ else
+ print_debug("Unknown character in labyrinth file: '%c'"
+ " = %X",
+ ch, ch);
+
+ if (x == LABYRINTH_MAXWIDTH)
+ {
+ x = 0;
+ y++;
+ firstline = 0;
+ labyrinth.height++;
+ }
+ if (y == LABYRINTH_MAXHEIGHT)
+ {
+ print_error("Labyrinth overflow");
+ exit(1);
+ }
+ }
+
+ hero.x = start.x;
+ hero.y = start.y;
+ labyrinth.cells[hero.y][hero.x] = CELL_HERO;
+
+ 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 rect;
+ SDL_Rect bg_rect, cell_rect;
+ SDL_FRect dest_rect;
int x, y;
int cx = screen_width / 2, cy = screen_height / 2;
- int cell_size = 30;
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);
- rect.w = cell_size;
- rect.h = cell_size;
+ 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++)
{
- rect.x = cx - labyrinth.width / 2 * cell_size
- + x * cell_size;
- rect.y = cy - labyrinth.height / 2 * cell_size
- + y * cell_size;
-
- switch (labyrinth.cells[y][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))
{
- case CELL_WALL:
- SDL_SetRenderDrawColor(renderer, 128, 128, 128,
- SDL_ALPHA_OPAQUE);
- break;
- default:
- SDL_SetRenderDrawColor(renderer, 20, 20, 20,
- SDL_ALPHA_OPAQUE);
- break;
+ cell_rect.x = 1 + 7 * (CELL_SIZE + 1);
+ cell_rect.y = 1;
}
- SDL_RenderFillRect(renderer, &rect);
+ 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 - 30 * (TER16_WIDTH + 1), 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);
}
@@ -128,6 +558,8 @@ handle_event(SDL_Event* 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;
}
@@ -140,6 +572,24 @@ handle_event(SDL_Event* event)
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;
@@ -147,6 +597,126 @@ handle_event(SDL_Event* event)
}
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
+location_push(const SDL_Point* location)
+{
+ location_stack[location_pointer].x = location->x;
+ location_stack[location_pointer].y = location->y;
+ 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)
+{
+ SDL_Point backup;
+
+ if (hero.x == end.x && hero.y == end.y)
+ {
+ print_debug("next_step: Success");
+ state = STATE_SUCCESS;
+ }
+ else if (hero.x > 0 && passable(hero.x - 1, hero.y))
+ {
+ print_debug("next_step: Trying x-1, y: (%d, %d), "
+ "pushed to stack (%d, %d)",
+ hero.x - 1, hero.y, hero.x, hero.y);
+ labyrinth.cells[hero.y][hero.x] = CELL_OK;
+ location_push(&hero);
+ assign_point_xyIF(hero.x, hero.y, &animation.position);
+ assign_point_xyIF(hero.x - 1, hero.y, &animation.destination);
+ calculate_delta();
+ animation.step = 1;
+ animation.final_step = ANIM_STEPS;
+ animation.active = 1;
+ // labyrinth.cells[hero.y][hero.x] = CELL_HERO;
+ }
+ else if (hero.y > 0 && passable(hero.x, hero.y - 1))
+ {
+ print_debug("next_step: Trying x, y-1: (%d, %d), "
+ "pushed to stack (%d, %d)",
+ hero.x, hero.y - 1, hero.x, hero.y);
+ labyrinth.cells[hero.y][hero.x] = CELL_OK;
+ location_push(&hero);
+ assign_point_xyIF(hero.x, hero.y, &animation.position);
+ assign_point_xyIF(hero.x, hero.y - 1, &animation.destination);
+ calculate_delta();
+ animation.step = 1;
+ animation.final_step = ANIM_STEPS;
+ animation.active = 1;
+ // labyrinth.cells[hero.y][hero.x] = CELL_HERO;
+ }
+ else if (hero.x + 1 < labyrinth.width && passable(hero.x + 1, hero.y))
+ {
+ print_debug("next_step: Trying x+1, y: (%d, %d), "
+ "pushed to stack (%d, %d)",
+ hero.x + 1, hero.y, hero.x, hero.y);
+ labyrinth.cells[hero.y][hero.x] = CELL_OK;
+ location_push(&hero);
+ assign_point_xyIF(hero.x, hero.y, &animation.position);
+ assign_point_xyIF(hero.x + 1, hero.y, &animation.destination);
+ calculate_delta();
+ animation.step = 1;
+ animation.final_step = ANIM_STEPS;
+ animation.active = 1;
+ // labyrinth.cells[hero.y][hero.x] = CELL_HERO;
+ }
+ else if (hero.y + 1 < labyrinth.height && passable(hero.x, hero.y + 1))
+ {
+ print_debug("next_step: Trying x, y+1: (%d, %d), "
+ "pushed to stack (%d, %d)",
+ hero.x, hero.y + 1, hero.x, hero.y);
+ labyrinth.cells[hero.y][hero.x] = CELL_OK;
+ location_push(&hero);
+ assign_point_xyIF(hero.x, hero.y, &animation.position);
+ assign_point_xyIF(hero.x, hero.y + 1, &animation.destination);
+ calculate_delta();
+ animation.step = 1;
+ animation.final_step = ANIM_STEPS;
+ animation.active = 1;
+ // labyrinth.cells[hero.y][hero.x] = CELL_HERO;
+ }
+ else
+ {
+ /* Back up */
+ if (location_pop(&backup))
+ {
+ print_debug("State: failure");
+ state = STATE_FAILURE;
+ }
+ else
+ {
+ print_debug("Backing up, stack pop: %d, %d", backup.x,
+ backup.y);
+ labyrinth.cells[hero.y][hero.x] = CELL_FAIL;
+ assign_pointIF(&hero, &animation.position);
+ assign_pointIF(&backup, &animation.destination);
+ calculate_delta();
+ animation.step = 1;
+ animation.final_step = ANIM_STEPS;
+ animation.active = 1;
+ }
+ }
+ redraw = 1;
+}
+
+int
main(void)
{
SDL_Event event;
@@ -173,46 +743,36 @@ main(void)
SDL_SetWindowTitle(window, WIN_TITLE);
SDL_RenderSetVSync(renderer, 1);
- labyrinth.width = 10;
- labyrinth.height = 10;
- labyrinth.cells = (char**)calloc(labyrinth.height, sizeof(char*));
- if (!labyrinth.cells)
- {
- print_error("calloc failed");
- exit(1);
- }
- for (int y = 0; y < labyrinth.height; y++)
- {
- labyrinth.cells[y] = (char*)calloc(labyrinth.width, 1);
- if (!labyrinth.cells[y])
- {
- print_error("calloc failed");
- exit(1);
- }
- }
-
- labyrinth.cells[0][0] = CELL_WALL;
- labyrinth.cells[0][1] = CELL_WALL;
- labyrinth.cells[0][9] = CELL_WALL;
- labyrinth.cells[1][2] = CELL_WALL;
- labyrinth.cells[1][9] = CELL_WALL;
- labyrinth.cells[9][0] = CELL_WALL;
- labyrinth.cells[9][9] = CELL_WALL;
-
+ load_textures();
+ load_labyrinth("lavirint.dat");
+ location_stack
+ = (SDL_Point*)calloc(LOCATION_STACK_MAX, sizeof(SDL_Point));
update_size();
+ animation.active = 0;
while (running)
{
while (SDL_PollEvent(&event))
handle_event(&event);
- if (redraw)
- {
+ if (animation.active)
draw();
- redraw = 0;
- }
+ else
+ {
+ if (state == STATE_SEARCHING)
+ {
+ next_step();
+ SDL_Delay(SEARCHING_DELAY);
+ }
- SDL_Delay(10);
+ if (redraw)
+ {
+ draw();
+ redraw = 0;
+ }
+
+ SDL_Delay(10);
+ }
}
return 0;
diff --git a/lav-sdl.do b/lav-sdl.do
@@ -1,4 +1,5 @@
redo-ifchange lav-sdl.o
CFLAGS=${CFLAGS:- -Wall}
LIBS=$(pkg-config --libs sdl2)
+LIBS="$LIBS $(pkg-config --libs SDL2_image)"
gcc $CFLAGS -o $3 lav-sdl.o $LIBS
diff --git a/lavirint.dat b/lavirint.dat
@@ -0,0 +1,13 @@
+1 1
+24 11
+0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0
+1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 0 1 0
+0 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 0 1 0 1 0 1 1 0
+0 1 1 1 0 1 0 1 0 1 0 1 0 1 1 0 1 1 0 1 0 0 1 0
+0 1 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 1 0 1 0
+0 1 0 1 1 1 1 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 0
+0 1 0 1 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0
+0 1 0 1 0 1 0 1 0 1 1 1 0 1 0 1 1 1 0 1 1 1 1 1
+0 1 0 0 0 1 0 1 0 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1
+0 1 1 1 0 1 0 1 1 1 0 1 0 1 0 1 0 1 1 1 0 1 0 1
+0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0
diff --git a/sprites.png b/sprites.png
Бинарне датотеке се разликују.
diff --git a/ter16.png b/ter16.png
Бинарне датотеке се разликују.