From 3dac1b13d77ef01adf61b0f8e409fd78bf6e7aa7 Mon Sep 17 00:00:00 2001 From: Linus Probert Date: Mon, 6 Oct 2025 14:58:40 +0200 Subject: [PATCH 1/2] New minimap The minimap will now correctly render rooms according to shape and layout. Walls, pits, traps, doors and level exit are represented. Next step is to allow for a larger view of the map to be togglable. --- CMakeLists.txt | 2 +- src/gui.c | 116 +++++++++++++++++++++++++++++++++++++------------ src/gui.h | 28 +++++++++++- src/input.c | 1 - src/main.c | 16 +++++-- src/map.c | 17 +++++--- src/map.h | 35 ++++++++------- src/player.c | 1 + src/skill.c | 1 + 9 files changed, 161 insertions(+), 56 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index faf30d66..086ac27b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,7 +213,7 @@ set(INCLUDE_DIRS add_executable(${PROJECT_NAME}) add_subdirectory(src) add_subdirectory(lib/sqlite3) -set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 99) +set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 11) target_include_directories(${PROJECT_NAME} PRIVATE ${INCLUDE_DIRS}) if (NOT MSVC) diff --git a/src/gui.c b/src/gui.c index f324ff1d..79155185 100644 --- a/src/gui.c +++ b/src/gui.c @@ -23,6 +23,12 @@ #include #include "gui.h" +#include "SDL3/SDL_blendmode.h" +#include "SDL3/SDL_pixels.h" +#include "SDL3/SDL_render.h" +#include "defines.h" +#include "roommatrix.h" +#include "texture.h" #include "util.h" #include "map.h" #include "texturecache.h" @@ -186,10 +192,22 @@ init_sprites(Gui *gui, Camera *cam) BOTTOM_GUI_HEIGHT/16, cam); - gui->miniMapFrame = gui_util_create_frame_sprite(RIGHT_GUI_WIDTH/16, - MINIMAP_GUI_HEIGHT/16, - cam); - + Sprite *minimap = sprite_create(); + Texture *texture = texture_create(); + texture->dim = (Dimension) { + RIGHT_GUI_WIDTH, + MINIMAP_GUI_HEIGHT + }; + minimap->textures[0] = texture; + minimap->destroyTextures = true; + minimap->pos = (Position) { 0, 4 }; + minimap->dim = (Dimension) { RIGHT_GUI_WIDTH, MINIMAP_GUI_HEIGHT }; + minimap->fixed = true; + texture_create_blank(texture, + SDL_TEXTUREACCESS_TARGET, + cam->renderer); + + gui->miniMap = minimap; texture_load_from_text(gui->labels[KEY_LABEL]->textures[0], "Keys:", C_WHITE, C_BLACK, cam->renderer); gui->labels[KEY_LABEL]->dim = gui->labels[KEY_LABEL]->textures[0]->dim; @@ -453,27 +471,72 @@ gui_render_panel(Gui *gui, Camera *cam) } void -gui_render_minimap(Gui *gui, Map *map, Camera *cam) +gui_update_minimap(Gui *gui, Camera *cam, RoomMatrix *rm) { - sprite_render(gui->miniMapFrame, cam); - - SDL_FRect box = { 0.0f, 0.0f, 12.0f, 8.0f }; - for (Uint8 i = 0; i < MAP_H_ROOM_COUNT; ++i) { - for (Uint8 j = 0; j < MAP_V_ROOM_COUNT; ++j) { - Room *room = map->rooms[i][j]; - box.x = (float) i*14 + 10; - box.y = (float) j*10 + 14; - if (room && room->visited) { - if (map->currentRoom.x == i && map->currentRoom.y == j) - SDL_SetRenderDrawColor(cam->renderer, 0, 255, 255, 255); - else - SDL_SetRenderDrawColor(cam->renderer, 255, 255, 255, 255); - SDL_RenderFillRect(cam->renderer, &box); - SDL_SetRenderDrawColor(cam->renderer, 60, 134, 252, 255); - SDL_RenderRect(cam->renderer, &box); + (void) gui; + (void) cam; + + SDL_SetRenderTarget(cam->renderer, gui->miniMap->textures[0]->texture); + SDL_SetRenderDrawColor(cam->renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); + + debug("Updating minimap"); + + for (size_t i = 0; i < MAP_ROOM_WIDTH; ++i) { + for (size_t j = 0; j < MAP_ROOM_HEIGHT; ++j) { + const RoomSpace* space = &rm->spaces[i][j]; + const float x = (float)(i + rm->roomPos.x * MAP_ROOM_WIDTH); + const float y = (float)(j + rm->roomPos.y * MAP_ROOM_HEIGHT); + + SDL_Color c = {0, 0, 0, SDL_ALPHA_OPAQUE }; + if (SPACE_IS_LETHAL(space)) { + c.a = SDL_ALPHA_TRANSPARENT; + } else if (space->trap) { + c.r = 255; + } else if (space->door) { + c.r = 0; c.g = 0; c.b = 255; + } else if (space->tile && space->tile->levelExit) { + c.r = 0; c.g = 255; c.b = 0; + } else if (space->wall || SPACE_IS_OCCUPIED(space)) { + c.r = 200; c.g = 200; c.b = 200; + } else if (space->tile == NULL) { + c.r = 0; c.g = 0; c.b = 0; + } else if (SPACE_IS_WALKABLE(space)) { + c.r = 94; c.g = 77; c.b = 179; + } else { + c.r = 200; c.g = 200; c.b = 200; } + + SDL_SetRenderDrawColor(cam->renderer, c.r, c.g, c.b, c.a); + SDL_RenderPoint(cam->renderer, x, y); } } + + SDL_RenderPresent(cam->renderer); + SDL_SetRenderTarget(cam->renderer, NULL); + // TODO(Linus): Implement target rendering +} + +void +gui_reset(Gui *gui, Camera *cam) +{ + // Clear the minimap + SDL_SetRenderTarget(cam->renderer, gui->miniMap->textures[0]->texture); + SDL_SetRenderDrawColor(cam->renderer, 0, 0, 0, SDL_ALPHA_TRANSPARENT); + SDL_RenderClear(cam->renderer); + SDL_SetRenderTarget(cam->renderer, NULL); +} + +void +gui_render_minimap(Gui *gui, Camera *cam, RoomMatrix *rm) +{ + sprite_render(gui->miniMap, cam); + const SDL_FRect r = { + (float) rm->roomPos.x * MAP_ROOM_WIDTH, + 4.0f + (float) rm->roomPos.y * MAP_ROOM_HEIGHT, + MAP_ROOM_WIDTH, + MAP_ROOM_HEIGHT }; + SDL_SetRenderDrawColor(cam->renderer, 0, 255, 255, 100); + SDL_RenderRect(cam->renderer, &r); } void @@ -537,7 +600,7 @@ void gui_render_log(Gui *gui, Camera *cam) { SDL_Rect box = { 16, 0, 16, 16 }; - + sprite_render(gui->bottomFrame, cam); for (Uint32 i = 0; i < log_data.count; ++i) { @@ -622,7 +685,7 @@ destroy_event_messages(void) for (unsigned int i = 0; i < event_messages.count; ++i) { free(event_messages.messages[i]); } - + free(event_messages.messages); event_messages.messages = NULL; } @@ -638,7 +701,9 @@ gui_destroy(Gui *gui) sprite_destroy(gui->bottomFrame); sprite_destroy(gui->statsFrame); - sprite_destroy(gui->miniMapFrame); + sprite_destroy(gui->miniMap); + sprite_destroy(gui->silverKey); + sprite_destroy(gui->goldKey); while (gui->sprites != NULL) sprite_destroy(linkedlist_pop(&gui->sprites)); @@ -653,8 +718,5 @@ gui_destroy(Gui *gui) for (int i = 0; i < LABEL_COUNT; ++i) sprite_destroy(gui->labels[i]); - sprite_destroy(gui->silverKey); - sprite_destroy(gui->goldKey); - free(gui); } diff --git a/src/gui.h b/src/gui.h index c942baf3..ddc16f4d 100644 --- a/src/gui.h +++ b/src/gui.h @@ -19,6 +19,7 @@ #ifndef GUI_H_ #define GUI_H_ +#include "roommatrix.h" #define LOG_LINES_COUNT 10 #define LOG_FONT_SIZE 8 #define LABEL_FONT_SIZE 8 @@ -49,7 +50,7 @@ typedef struct Gui { LinkedList *xp_bar; Sprite *bottomFrame; Sprite *statsFrame; - Sprite *miniMapFrame; + Sprite *miniMap; Sprite *labels[LABEL_COUNT]; Sprite *activeTooltip; Sprite *goldKey; @@ -68,8 +69,31 @@ gui_update_player_stats(Gui*, Player*, Map*, SDL_Renderer*); void gui_render_panel(Gui*, Camera*); +/** + * \brief Update the minimap with the current room + * \param[in] gui The gui + * \param[in] cam The camera + * \param[in] rm The current rooms RoomMatrix + */ +void +gui_update_minimap(Gui *gui, Camera *cam, RoomMatrix *rm); + +/** + * \brief Reset the gui + * \param gui The gui + * \param cam The camera + */ +void +gui_reset(Gui *gui, Camera *cam); + +/** + * \brief Render the minimap + * \param[in] gui The gui + * \param[in] cam The camera + * \param[in] rm The room matrix + */ void -gui_render_minimap(Gui*, Map*, Camera*); +gui_render_minimap(Gui *gui, Camera *cam, RoomMatrix *rm); void gui_render_log(Gui*, Camera*); diff --git a/src/input.c b/src/input.c index 19fe9f48..d9e529da 100644 --- a/src/input.c +++ b/src/input.c @@ -17,7 +17,6 @@ */ #include "input.h" -#include "vector2d.h" void input_init(Input *input) diff --git a/src/main.c b/src/main.c index e7ded709..3af4a30d 100644 --- a/src/main.c +++ b/src/main.c @@ -454,7 +454,7 @@ goToMainMenu(void *unused) initMainMenu(); Position p = { 0, 0 }; gPlayer->sprite->pos = (Position) { 32, 32 }; - map_set_current_room(gMap, &p); + map_set_current_room(gMap, &p, NULL); camera_follow_position(gCamera, &p); } @@ -663,9 +663,12 @@ resetGame(void) player_reset_on_levelchange(gPlayer); - map_set_current_room(gMap, &gPlayer->sprite->pos); + map_set_current_room(gMap, &gPlayer->sprite->pos, NULL); camera_follow_position(gCamera, &gPlayer->sprite->pos); repopulate_roommatrix(); + + gui_reset(gGui, gCamera); + gui_update_minimap(gGui, gCamera, gRoomMatrix); } static void @@ -949,6 +952,7 @@ static void run_game_update(void) { static UpdateData updateData; + bool first_room_visit = false; if (gGameState == IN_GAME_MENU) menu_update(inGameMenu, &input, gCamera); @@ -972,7 +976,7 @@ run_game_update(void) actiontextbuilder_update(&updateData); skillbar_update(gSkillBar, &updateData); camera_follow_position(gCamera, &gPlayer->sprite->pos); - map_set_current_room(gMap, &gPlayer->sprite->pos); + map_set_current_room(gMap, &gPlayer->sprite->pos, &first_room_visit); map_update(&updateData); if (currentTurn == PLAYER) { @@ -989,6 +993,10 @@ run_game_update(void) map_clear_expired_entities(gMap, gRoomMatrix, gPlayer); repopulate_roommatrix(); + + if (first_room_visit) { + gui_update_minimap(gGui, gCamera, gRoomMatrix); + } } static void @@ -997,7 +1005,7 @@ render_gui(void) SDL_SetRenderViewport(gRenderer, &statsGuiViewport); gui_render_panel(gGui, gCamera); SDL_SetRenderViewport(gRenderer, &minimapViewport); - gui_render_minimap(gGui, gMap, gCamera); + gui_render_minimap(gGui, gCamera, gRoomMatrix); SDL_SetRenderViewport(gRenderer, &skillBarViewport); skillbar_render(gSkillBar, gPlayer, gCamera); SDL_SetRenderViewport(gRenderer, &bottomGuiViewport); diff --git a/src/map.c b/src/map.c index 82812b7d..7c17a98c 100644 --- a/src/map.c +++ b/src/map.c @@ -22,6 +22,7 @@ #include "util.h" #include "item.h" #include "item_builder.h" +#include "object.h" #include "gui.h" #include "particle_engine.h" #include "update_data.h" @@ -398,24 +399,24 @@ map_render_top_layer(Map *map, RoomMatrix *rm, Camera *cam) } } -void map_set_current_room(Map *map, Position *pos) +void map_set_current_room(Map *map, Position *player_world_pos, bool *first_visit) { unsigned int room_width, room_height; room_width = MAP_ROOM_WIDTH * TILE_DIMENSION; room_height = MAP_ROOM_HEIGHT * TILE_DIMENSION; - if (pos->x <= 0) { + if (player_world_pos->x <= 0) { map->currentRoom.x = 0; } else { - unsigned int room_cord_x = pos->x - (pos->x % room_width); + unsigned int room_cord_x = player_world_pos->x - (player_world_pos->x % room_width); map->currentRoom.x = room_cord_x / room_width; } - if (pos->y <= 0) { + if (player_world_pos->y <= 0) { map->currentRoom.y = 0; } else { - unsigned int room_cord_y = pos->y - (pos->y % room_height); + unsigned int room_cord_y = player_world_pos->y - (player_world_pos->y % room_height); map->currentRoom.y = room_cord_y / room_height; } @@ -424,7 +425,11 @@ void map_set_current_room(Map *map, Position *pos) if (map->currentRoom.y >= MAP_V_ROOM_COUNT) map->currentRoom.y = MAP_V_ROOM_COUNT - 1; - map->rooms[map->currentRoom.x][map->currentRoom.y]->visited = true; + Room *room = map->rooms[map->currentRoom.x][map->currentRoom.y]; + if (first_visit != NULL) { + *first_visit = !room->visited; + } + room->visited = true; } static diff --git a/src/map.h b/src/map.h index 15fa3321..0141c3bc 100644 --- a/src/map.h +++ b/src/map.h @@ -31,12 +31,8 @@ #include "monster.h" #include "player.h" #include "map_room_modifiers.h" -#include "object.h" #include "doorlocktype.h" -typedef struct UpdateData UpdateData; -typedef struct Trap Trap; - typedef struct MapTile_t { Sprite *sprite; bool collider; @@ -58,17 +54,20 @@ typedef struct Room_t { unsigned int lockTypes; } Room; +/** + * \brief Map struct + */ typedef struct Map_t { - Room* rooms[MAP_H_ROOM_COUNT][MAP_V_ROOM_COUNT]; - LinkedList *textures; - LinkedList *monsters; - LinkedList *items; - LinkedList *artifacts; - LinkedList *objects; - Position currentRoom; - Timer *monsterMoveTimer; - int level; - unsigned int lockTypes; + Room* rooms[MAP_H_ROOM_COUNT][MAP_V_ROOM_COUNT]; /**< Rooms */ + LinkedList *textures; /**< Texture list */ + LinkedList *monsters; /**< Monster list */ + LinkedList *items; /**< Item list */ + LinkedList *artifacts; /**< Artifact list */ + LinkedList *objects; /**< Object list */ + Position currentRoom; /**< Current room (room index) */ + Timer *monsterMoveTimer; /**< Monster move timer */ + int level; /**< Level (depth) */ + unsigned int lockTypes; /**< Lock types in map */ } Map; Map* @@ -119,8 +118,14 @@ map_render_mid_layer(Map*, Camera*); void map_render_top_layer(Map*, RoomMatrix*, Camera*); +/** + * \brief Set the current room based on player position + * \param[in] map The map + * \param[in] pos The players current world position + * \param[out] first_visit Set to true if this is the first visit to this room + */ void -map_set_current_room(Map*, Position*); +map_set_current_room(Map* map, Position* player_world_pos, bool* first_visit); void map_trigger_tile_fall(MapTile *tile); diff --git a/src/player.c b/src/player.c index ec76d15f..1313f347 100644 --- a/src/player.c +++ b/src/player.c @@ -36,6 +36,7 @@ #include "gamecontroller.h" #include "event.h" #include "effect_util.h" +#include "object.h" #ifdef STEAM_BUILD #include "steam/steamworks_api_wrapper.h" diff --git a/src/skill.c b/src/skill.c index 351a46cf..9b77ae9d 100644 --- a/src/skill.c +++ b/src/skill.c @@ -38,6 +38,7 @@ #include "tooltip.h" #include "actiontextbuilder.h" #include "effect_util.h" +#include "object.h" static char *flurry_tooltip[] = { "FLURRY", "", From f07cb219d2567cc063aded0faff6747c60c05333 Mon Sep 17 00:00:00 2001 From: Linus Probert Date: Tue, 7 Oct 2025 00:11:57 +0200 Subject: [PATCH 2/2] Review fixes --- src/gui.c | 5 ----- src/map.h | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/gui.c b/src/gui.c index 79155185..009d29de 100644 --- a/src/gui.c +++ b/src/gui.c @@ -473,9 +473,6 @@ gui_render_panel(Gui *gui, Camera *cam) void gui_update_minimap(Gui *gui, Camera *cam, RoomMatrix *rm) { - (void) gui; - (void) cam; - SDL_SetRenderTarget(cam->renderer, gui->miniMap->textures[0]->texture); SDL_SetRenderDrawColor(cam->renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); @@ -511,9 +508,7 @@ gui_update_minimap(Gui *gui, Camera *cam, RoomMatrix *rm) } } - SDL_RenderPresent(cam->renderer); SDL_SetRenderTarget(cam->renderer, NULL); - // TODO(Linus): Implement target rendering } void diff --git a/src/map.h b/src/map.h index 0141c3bc..0de06fc9 100644 --- a/src/map.h +++ b/src/map.h @@ -33,6 +33,9 @@ #include "map_room_modifiers.h" #include "doorlocktype.h" +typedef struct UpdateData UpdateData; +typedef struct Trap Trap; + typedef struct MapTile_t { Sprite *sprite; bool collider;