lav-sdl

SDL верзија програма Лавиринт
git clone https://git.sr.ht/~strahinja/lav-sdl
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување 398d7d42d7df8a8de8fbdd831cb805b62b9c302d
родитељ 7c8cb914a1295544e7680c2ce84fc183505ab362
Аутор: Страхиња Радић <sr@strahinja.org>
Датум:   Tue,  8 Jul 2025 22:17:27 +0200

WIP switch to SDL3; better font handling

Diffstat:
Mconfig.mk | 8++++----
Mlav-sdl.c | 204++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
измењених датотека: 2, додавања: 118(+), брисања: 94(-)

diff --git a/config.mk b/config.mk @@ -2,13 +2,13 @@ CFLAGS = -Os -Wall -pedantic -std=c99 _CPPFLAGS = -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L \ -D_XOPEN_SOURCE=700 -INCLUDE = -I/usr/include/SDL2 +INCLUDE = -I/usr/include # OpenBSD #_CPPFLAGS = -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L \ # -D_XOPEN_SOURCE=700 -D_BSD_SOURCE -#INCLUDE = -I/usr/local/include/SDL2 +#INCLUDE = -I/usr/local/include INSTALL = install -LIBS = -lSDL2_image -lSDL2 -lm +LIBS = -lSDL3_image -lSDL3 -lm SRC = lav-sdl.c HEADERS = local.h OBJS = lav-sdl.o @@ -20,7 +20,7 @@ BINDIR = $(PREFIX)/bin CPPFLAGS = $(_CPPFLAGS) $(INCLUDE) DATADIR = $(PREFIX)/share/$(PROG) DOCDIR = $(PREFIX)/share/doc/$(PROG) -#MANPREFIX = $(PREFIX)/share/man +MANPREFIX = $(PREFIX)/share/man # OpenBSD #MANPREFIX = $(PREFIX)/man #MANPAGE = $(PROG).1 diff --git a/lav-sdl.c b/lav-sdl.c @@ -2,8 +2,8 @@ * any later version. Copyright (C) 2023-2024 Strahinya Radich. * See the file LICENSE for exact copyright and license details. */ -#include <SDL.h> -#include <SDL_image.h> +#include <SDL3/SDL.h> +#include <SDL3_image/SDL_image.h> #include <errno.h> #include <math.h> #include <stdarg.h> @@ -17,16 +17,16 @@ #define CELL_SIZE 32 #define DEFAULT_WIDTH 1280 #define DEFAULT_HEIGHT 720 -#define HELP_DIALOG_WIDTH 640 -#define HELP_DIALOG_HEIGHT 300 +#define HELP_DIALOG_WIDTH 1200 +#define HELP_DIALOG_HEIGHT 600 #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 TER16_HEIGHT 17 +#define SEARCHING_DELAY 0 #define TER16_WIDTH 8 +#define TER16_HEIGHT 17 #define WIN_TITLE "Lavirint (SDL version)" #define MIN(a, b) (((a) < (b)) ? (a) : (b)) @@ -106,19 +106,20 @@ static int state = STATE_SEARCHING_PAUSED; static SDL_Texture* ter16_texture = NULL; static SDL_Texture* background = NULL; static SDL_Window* window = NULL; +static float text_scale_factor = 2.0f; 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_background(SDL_Rect* bg_rect, SDL_Rect* cell_rect, +void draw_background(SDL_FRect* bg_rect, SDL_FRect* cell_rect, SDL_FRect* dest_rect); void draw_help_dialog(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_hero_sprite_xy(int* x, int* y); -void get_sprite_xy(const char cell, int* x, int* y); +void get_hero_sprite_xy(float* x, float* y); +void get_sprite_xy(const char cell, float* x, float* y); void handle_event(SDL_Event* event); void labyrinth_coord_to_screen_coord(const int x, const int y, const float startx, const float starty, float* to_x, float* to_y); @@ -186,17 +187,19 @@ cleanup(void) if (window) SDL_DestroyWindow(window); - IMG_Quit(); + // IMG_Quit(); SDL_Quit(); } void draw(void) { - SDL_Rect bg_rect, cell_rect; + SDL_FRect bg_rect, cell_rect; SDL_FRect dest_rect; int x, y; int cx, cy; + float crx, cry; + float drx, dry; float startx, starty; cx = screen_width / 2; @@ -225,7 +228,7 @@ draw(void) dest_rect.y = starty; dest_rect.w = bg_rect.w; dest_rect.h = bg_rect.h; - SDL_RenderCopyF(renderer, background, &bg_rect, &dest_rect); + SDL_RenderTexture(renderer, background, &bg_rect, &dest_rect); /* Draw nuggets/cobwebs */ dest_rect.w = CELL_SIZE; @@ -239,26 +242,32 @@ draw(void) || (x == end.x && y == end.y)) continue; - get_sprite_xy(labyrinth.cells[y][x], &cell_rect.x, - &cell_rect.y); + get_sprite_xy(labyrinth.cells[y][x], &crx, &cry); + cell_rect.x = crx; + cell_rect.y = cry; labyrinth_coord_to_screen_coord(x, y, startx, starty, - &dest_rect.x, &dest_rect.y); - SDL_RenderCopyF(renderer, sprites, &cell_rect, + &drx, &dry); + dest_rect.x = drx; + dest_rect.y = dry; + SDL_RenderTexture(renderer, sprites, &cell_rect, &dest_rect); } /* Draw hero */ dest_rect.w = CELL_SIZE; dest_rect.h = CELL_SIZE; - get_hero_sprite_xy(&cell_rect.x, &cell_rect.y); + get_hero_sprite_xy(&crx, &cry); + cell_rect.x = crx; + cell_rect.y = cry; if (animation.active) labyrinth_coord_to_screen_coordF(animation.position.x, - animation.position.y, startx, starty, &dest_rect.x, - &dest_rect.y); + animation.position.y, startx, starty, &drx, &dry); else labyrinth_coord_to_screen_coord(hero.x, hero.y, startx, starty, - &dest_rect.x, &dest_rect.y); - SDL_RenderCopyF(renderer, sprites, &cell_rect, &dest_rect); + &drx, &dry); + dest_rect.x = drx; + dest_rect.y = dry; + SDL_RenderTexture(renderer, sprites, &cell_rect, &dest_rect); /* Render status */ draw_text(startx, starty + bg_rect.h, TER16_WIDTH, TER16_HEIGHT, @@ -273,18 +282,28 @@ draw(void) } void -draw_background(SDL_Rect* bg_rect, SDL_Rect* cell_rect, SDL_FRect* dest_rect) +draw_background(SDL_FRect* bg_rect, SDL_FRect* cell_rect, SDL_FRect* dest_rect) { - SDL_DisplayMode mode; + const SDL_DisplayMode* mode; + SDL_DisplayID display; + float crx, cry; + float drx, dry; + + if ((display = SDL_GetDisplayForWindow(window)) == 0) + { + print_error("SDL_GetDisplayForWindow failed: %s", + SDL_GetError()); + exit(1); + } - if (SDL_GetCurrentDisplayMode(0, &mode) < 0) + if ((mode = SDL_GetCurrentDisplayMode(display)) == NULL) { print_error("SDL_GetCurrentDisplayMode failed: %s", SDL_GetError()); exit(1); } - background = SDL_CreateTexture(renderer, mode.format, + background = SDL_CreateTexture(renderer, mode->format, SDL_TEXTUREACCESS_TARGET, bg_rect->w, bg_rect->h); if (!background) { @@ -292,7 +311,7 @@ draw_background(SDL_Rect* bg_rect, SDL_Rect* cell_rect, SDL_FRect* dest_rect) SDL_GetError()); exit(1); } - if (SDL_SetRenderTarget(renderer, background) < 0) + if (!SDL_SetRenderTarget(renderer, background)) { print_error("SDL_SetRenderTarget failed: %s", SDL_GetError()); exit(1); @@ -312,11 +331,15 @@ draw_background(SDL_Rect* bg_rect, SDL_Rect* cell_rect, SDL_FRect* dest_rect) || (x == end.x && y == end.y))) continue; - get_sprite_xy(labyrinth.cells[y][x], &cell_rect->x, - &cell_rect->y); - labyrinth_coord_to_screen_coord(x, y, 0.0f, 0.0f, - &dest_rect->x, &dest_rect->y); - SDL_RenderCopyF(renderer, sprites, cell_rect, dest_rect); + get_sprite_xy(labyrinth.cells[y][x], &crx, &cry); + cell_rect->x = crx; + cell_rect->y = cry; + labyrinth_coord_to_screen_coord(x, y, 0.0f, 0.0f, &drx, + &dry); + dest_rect->x = drx; + dest_rect->y = dry; + SDL_RenderTexture(renderer, sprites, cell_rect, + dest_rect); } SDL_SetRenderTarget(renderer, NULL); @@ -328,7 +351,7 @@ draw_help_dialog(void) const char** phelp_text = help_text; int sx = screen_width / 2 - HELP_DIALOG_WIDTH / 2; int sy = screen_height / 2 - HELP_DIALOG_HEIGHT / 2; - SDL_Rect dialog_rect; + SDL_FRect dialog_rect; dialog_rect.x = sx; dialog_rect.y = sy; @@ -341,24 +364,25 @@ draw_help_dialog(void) SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); - SDL_RenderDrawRect(renderer, &dialog_rect); + SDL_RenderRect(renderer, &dialog_rect); SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); dialog_rect.x--; dialog_rect.y--; dialog_rect.w += 2; dialog_rect.h += 2; - SDL_RenderDrawRect(renderer, &dialog_rect); + SDL_RenderRect(renderer, &dialog_rect); dialog_rect.x--; dialog_rect.y--; dialog_rect.w += 2; dialog_rect.h += 2; - SDL_RenderDrawRect(renderer, &dialog_rect); + SDL_RenderRect(renderer, &dialog_rect); while (*phelp_text) { - draw_text(sx + (2 * TER16_WIDTH), - sy + (TER16_HEIGHT + 2) - + (phelp_text - help_text) * (TER16_HEIGHT + 2), + draw_text(sx + text_scale_factor * (2 * TER16_WIDTH), + sy + text_scale_factor * (TER16_HEIGHT + 2) + + (phelp_text - help_text) * text_scale_factor + * (TER16_HEIGHT + 2), TER16_WIDTH, TER16_HEIGHT, ter16_texture, *phelp_text); phelp_text++; } @@ -373,13 +397,13 @@ draw_text(const int x, const int y, const int font_width, const int font_height, const char* pbuf = NULL; int xstart = 0; int ystart = 0; - SDL_Rect source_rect; + SDL_FRect 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; + float tex_w, tex_h; if (!text || !font_tex) return; @@ -393,18 +417,19 @@ draw_text(const int x, const int y, const int font_width, const int font_height, dest_rect.x = x; dest_rect.y = y; - dest_rect.w = font_width; - dest_rect.h = font_height; + dest_rect.w = text_scale_factor * font_width; + dest_rect.h = text_scale_factor * font_height; - if (SDL_QueryTexture(font_tex, NULL, NULL, &tex_w, &tex_h) < 0) + if (!SDL_GetTextureSize(font_tex, &tex_w, &tex_h)) { - print_error("SDL_QueryTexture failed: %s", SDL_GetError()); + print_error("SDL_GetTextureSize failed: %s", SDL_GetError()); exit(1); } chars_per_row = tex_w / (font_width + 1); pbuf = buf; + // SDL_SetRenderScale(renderer, scale_factor, scale_factor); while (*pbuf) { if (*pbuf >= first_char && *pbuf <= last_char) @@ -420,16 +445,17 @@ draw_text(const int x, const int y, const int font_width, const int font_height, source_rect.x = xstart; source_rect.y = ystart; - SDL_RenderCopyF(renderer, font_tex, &source_rect, &dest_rect); + SDL_RenderTexture(renderer, font_tex, &source_rect, &dest_rect); - dest_rect.x += font_width; + dest_rect.x += text_scale_factor * font_width; pbuf++; } + // SDL_SetRenderScale(renderer, 1.0f, 1.0f); } void -get_hero_sprite_xy(int* x, int* y) +get_hero_sprite_xy(float* x, float* y) { switch (state) { @@ -449,7 +475,7 @@ get_hero_sprite_xy(int* x, int* y) } void -get_sprite_xy(const char cell, int* x, int* y) +get_sprite_xy(const char cell, float* x, float* y) { switch (cell) { @@ -477,35 +503,28 @@ get_sprite_xy(const char cell, int* x, int* y) *x = 1 + 5 * (CELL_SIZE + 1); *y = 1; } + /*print_debug("get_sprite_xy: %d @ (%0.0f, %0.0f)", + cell, *x, *y);*/ } void handle_event(SDL_Event* event) { - SDL_Keysym keysym; - if (!event) return; switch (event->type) { - case SDL_QUIT: + case SDL_EVENT_QUIT: running = 0; break; - case SDL_WINDOWEVENT: - switch (event->window.event) - { - case SDL_WINDOWEVENT_RESIZED: - redraw = 1; - break; - } + case SDL_EVENT_WINDOW_RESIZED: + redraw = 1; break; - case SDL_KEYDOWN: - keysym = event->key.keysym; - - print_debug("Got Keydown, sym = %X, mod = %X", keysym.sym, - keysym.mod); + case SDL_EVENT_KEY_DOWN: + print_debug("Got Keydown, key = %X, mod = %X", event->key.key, + event->key.mod); - switch (keysym.sym) + switch (event->key.key) { case SDLK_F1: help_shown = 1; @@ -532,23 +551,23 @@ handle_event(SDL_Event* event) reset(); } break; - case SDLK_q: - if (keysym.mod & KMOD_CTRL) + case SDLK_Q: + if (event->key.mod & SDL_KMOD_CTRL) running = 0; break; default: print_debug("switch fallthrough"); } break; - case SDL_MOUSEMOTION: + case SDL_EVENT_MOUSE_MOTION: pointer.x = event->motion.x; pointer.y = event->motion.y; if (pointer.x <= 0 || pointer.y <= 0 || pointer.x + 1 >= screen_width || pointer.y + 1 >= screen_height) - SDL_ShowCursor(1); + SDL_ShowCursor(); else - SDL_ShowCursor(0); + SDL_HideCursor(); break; } } @@ -572,7 +591,8 @@ labyrinth_coord_to_screen_coordF(const float x, const float y, int load_textures(void) { - SDL_Surface* surface = NULL; + SDL_Surface* surface = NULL; + SDL_ScaleMode scale_mode = SDL_SCALEMODE_PIXELART; surface = try_load(SPRITES_PNG); if (!surface) @@ -584,7 +604,8 @@ load_textures(void) SDL_GetError()); exit(1); } - SDL_FreeSurface(surface); + SDL_SetTextureScaleMode(sprites, scale_mode); + SDL_DestroySurface(surface); surface = try_load(TER16_PNG); if (!surface) @@ -596,8 +617,8 @@ load_textures(void) SDL_GetError()); exit(1); } - - SDL_FreeSurface(surface); + SDL_SetTextureScaleMode(ter16_texture, scale_mode); + SDL_DestroySurface(surface); return 0; } @@ -869,14 +890,14 @@ try_load(const char* filename) if (!surface) { print_debug("try_load: IMG_Load failed (%s): %s", tex_pathname, - IMG_GetError()); + SDL_GetError()); snprintf(tex_pathname, BUFSIZE, "./%s", filename); print_debug("try_load: trying %s", tex_pathname); surface = IMG_Load(tex_pathname); if (!surface) { print_error("try_load: IMG_Load failed (%s): %s", - tex_pathname, IMG_GetError()); + tex_pathname, SDL_GetError()); exit(1); } } @@ -888,33 +909,36 @@ int main(int argc, char** argv) { SDL_Event event; - int px, py; + float px, py; char datafile_pathname[BUFSIZE]; atexit(&cleanup); - if (SDL_Init(SDL_INIT_VIDEO) < 0) + if (!SDL_Init(SDL_INIT_VIDEO)) { print_error("SDL_Init failed: %s", SDL_GetError()); exit(1); } - if (SDL_CreateWindowAndRenderer(DEFAULT_WIDTH, DEFAULT_HEIGHT, - SDL_WINDOW_SHOWN | SDL_WINDOW_MAXIMIZED - | SDL_WINDOW_FULLSCREEN_DESKTOP - | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE, - &window, &renderer) - < 0) + if (!SDL_CreateWindowAndRenderer(WIN_TITLE, DEFAULT_WIDTH, + DEFAULT_HEIGHT, SDL_WINDOW_MAXIMIZED | SDL_WINDOW_RESIZABLE, + &window, &renderer)) { print_error("SDL_CreateWindowAndRenderer failed: %s", SDL_GetError()); exit(1); } - SDL_SetWindowTitle(window, WIN_TITLE); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); + SDL_SetWindowFullscreenMode(window, NULL); + SDL_SetWindowFullscreen(window, 1); SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC, "1", SDL_HINT_OVERRIDE); - SDL_RenderSetLogicalSize(renderer, DEFAULT_WIDTH, DEFAULT_HEIGHT); + SDL_SetRenderLogicalPresentation(renderer, DEFAULT_WIDTH, + DEFAULT_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX); + /*SDL_SetRenderLogicalPresentation(renderer, DEFAULT_WIDTH, + DEFAULT_HEIGHT, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE);*/ + /*float factor = (float)714/720; + print_debug("factor = %0.2f", factor); + SDL_SetRenderScale(renderer, 1.0f, factor);*/ if (load_textures() < 0) exit(1); @@ -947,10 +971,10 @@ main(int argc, char** argv) = (SDL_Point*)calloc(LOCATION_STACK_MAX, sizeof(SDL_Point)); animation.active = 0; - SDL_ShowCursor(0); + SDL_HideCursor(); SDL_GetMouseState(&px, &py); - pointer.x = (float)px; - pointer.y = (float)py; + pointer.x = px; + pointer.y = py; while (running) { while (SDL_PollEvent(&event)) @@ -975,7 +999,7 @@ main(int argc, char** argv) } } /* TODO: More sophisticated framerate/vsync/delay handling */ - SDL_Delay(10); + SDL_Delay(SEARCHING_DELAY); } return 0;