From d9219a8c647cb2a3a97eed7e62a6cc22b67f40fe Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sat, 12 Jul 2025 00:35:57 -0400 Subject: [PATCH] This cleans up how I'm rendering the map but there's no way I can render a large map like this. It'd be way too big. --- tests/map.cpp | 84 +++++++++++++++++++++++++-------------------------- textures.cpp | 28 +++++++++++++++++ textures.hpp | 4 +++ 3 files changed, 74 insertions(+), 42 deletions(-) diff --git a/tests/map.cpp b/tests/map.cpp index 8a0f0b4..f39d6f2 100644 --- a/tests/map.cpp +++ b/tests/map.cpp @@ -80,71 +80,71 @@ TEST_CASE("dijkstra algo test", "[map]") { } } -sf::Sprite render_sprite(std::unordered_map& sprite_coord, sf::Vector2i size, wchar_t display, sf::Texture& map_sprites) { - auto coords = sprite_coord.at(display); - sf::IntRect square{coords, {size.x, size.y}}; - sf::Sprite sprite{map_sprites, square}; - return sprite; -} - - -TEST_CASE("map image test", "[map-sprite]") { - components::init(); - textures::init(); - LevelManager levels; - GameLevel level = levels.current(); +sf::Sprite render_map(GameLevel& level, sf::RenderTexture& render) { auto &walls = level.map->tiles(); + auto &tile_set = textures::get_map_tile_set(); sf::Vector2i size{MAP_TILE_DIM,MAP_TILE_DIM}; - matrix::dump("TILES?", walls); - - std::unordered_map sprite_coord; - - Config config("./assets/map_tiles.json"); - json& tiles = config.json(); - - for(auto tile : tiles) { - sf::Vector2i coords{tile["x"], tile["y"]}; - REQUIRE(coords.x % size.x == 0); - REQUIRE(coords.y % size.y == 0); - sprite_coord.insert_or_assign(tile["display"], coords); - } sf::Vector2u dim{ (unsigned int)matrix::width(walls) * size.x, (unsigned int)matrix::height(walls) * size.y}; - sf::RenderTexture render{dim}; - render.clear({0,0,0,0}); + bool worked = render.resize(dim); + dbc::check(worked, "Failed to resize map render target."); - sf::Texture map_sprites{"./assets/map_tiles.png"}; - sf::Texture paper{"./assets/ui/full_screen_paper.png"}; - sf::Sprite paper_sprite{paper}; - paper_sprite.scale({1.5f, 1.5f}); - paper_sprite.setPosition({-30.0f, -30.0f}); - render.draw(paper_sprite); + render.clear({0,0,0,0}); for(matrix::each_row it{walls}; it.next();) { size_t tid = walls[it.y][it.x]; wchar_t display = tile_set[tid]; - REQUIRE(sprite_coord.contains(display)); - auto sprite = render_sprite(sprite_coord, size, display, map_sprites); + auto& sprite = textures::get_map_sprite(display); sprite.setPosition({float(it.x * size.x), float(it.y * size.y)}); render.draw(sprite); } - level.world->query([&](auto, auto &pos, auto &entity_glyph) { - REQUIRE(sprite_coord.contains(entity_glyph.display)); + render.display(); + return sf::Sprite{render.getTexture()}; +} + +sf::Sprite render_entities(GameLevel& level, sf::Sprite& map_sprite, sf::RenderTexture& render) { + render.clear({0,0,0,0}); + render.draw(map_sprite); - auto sprite = render_sprite(sprite_coord, size, entity_glyph.display, map_sprites); - sprite.setPosition({float(pos.location.x * size.x), float(pos.location.y * size.y)}); + level.world->query([&](auto, auto &pos, auto &entity_glyph) { + auto sprite = textures::get_map_sprite(entity_glyph.display); + sprite.setPosition({float(pos.location.x * MAP_TILE_DIM), float(pos.location.y * MAP_TILE_DIM)}); render.draw(sprite); }); render.display(); - sf::Image out_img = render.getTexture().copyToImage(); - bool worked = out_img.saveToFile("map_test.png"); + return sf::Sprite{render.getTexture()}; +} + +TEST_CASE("map image test", "[map-sprite]") { + components::init(); + textures::init(); + + LevelManager levels; + GameLevel level = levels.current(); + // on level start make one render texture with the base map + auto render = std::make_shared(); + auto map_sprite = render_map(level, *render); + + // every turn render the map to the entities texture, then render + // entities on this image, that way I just have to render them + auto entities = std::make_shared(render->getSize()); + render_entities(level, map_sprite, *entities); + + // confirm we get two different maps + auto out_img = render->getTexture().copyToImage(); + bool worked = out_img.saveToFile("map_render.png"); + REQUIRE(worked); + + // this has entities on it + out_img = entities->getTexture().copyToImage(); + worked = out_img.saveToFile("map_entities.png"); REQUIRE(worked); } diff --git a/textures.cpp b/textures.cpp index 81d4978..7d2c497 100644 --- a/textures.cpp +++ b/textures.cpp @@ -78,10 +78,31 @@ namespace textures { } } + void load_map_tiles() { + Config config("./assets/map_tiles.json"); + nlohmann::json& tiles = config.json(); + + for(auto tile : tiles) { + sf::Vector2i coords{tile["x"], tile["y"]}; + dbc::check(coords.x % ICONGEN_MAP_TILE_DIM == 0, "x coordinates wrong in map"); + dbc::check(coords.y % ICONGEN_MAP_TILE_DIM == 0, "y coordinates wrong in map"); + + sf::IntRect square{coords, {ICONGEN_MAP_TILE_DIM, ICONGEN_MAP_TILE_DIM}}; + sf::Sprite sprite{TMGR.map_sprite_sheet, square}; + wchar_t display = tile["display"]; + + dbc::check(!TMGR.map_sprites.contains(display), + fmt::format("duplicate tile display {} in map_tiles.json", int(display))); + + TMGR.map_sprites.try_emplace(display, sprite); + } + } + void init() { if(!initialized) { load_tiles(); load_sprites(); + load_map_tiles(); initialized = true; } } @@ -134,4 +155,11 @@ namespace textures { fmt::format("there is no texture named {} in tiles.json", name)); return TMGR.name_to_id.at(name); } + + sf::Sprite& get_map_sprite(wchar_t display) { + dbc::check(TMGR.map_sprites.contains(display), + fmt::format("map_sprites.json doesn't have {} sprite", int(display))); + + return TMGR.map_sprites.at(display); + } }; diff --git a/textures.hpp b/textures.hpp index 39841d6..2d24178 100644 --- a/textures.hpp +++ b/textures.hpp @@ -22,6 +22,8 @@ namespace textures { std::vector ambient_light; std::unordered_map sprite_textures; std::unordered_map name_to_id; + std::unordered_map map_sprites; + sf::Texture map_sprite_sheet{"./assets/map_tiles.png"}; }; void init(); @@ -40,5 +42,7 @@ namespace textures { const uint32_t* get_ceiling(size_t num); + sf::Sprite& get_map_sprite(wchar_t display); + size_t get_id(const std::string& name); }