From d6e2b64140fbf9b018a1f7c111eb74366a8c75f5 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Tue, 8 Jul 2025 13:09:39 -0400 Subject: [PATCH] icongen now makes a sprite sheet for the map which should be easier to work with. --- Makefile | 2 +- assets/map_tiles.png | Bin 0 -> 5991 bytes meson.build | 2 +- shiterator.hpp | 5 +- tools/icongen.cpp | 166 +++++++++++++++++++++++++++++++++---------- 5 files changed, 134 insertions(+), 41 deletions(-) create mode 100644 assets/map_tiles.png diff --git a/Makefile b/Makefile index 77b1ba6..e885866 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ else endif debug: build - gdb --nx -x .gdbinit --ex run --args builddir/zedcaster + gdb --nx -x .gdbinit --ex run --args builddir/icongen debug_run: build gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/zedcaster diff --git a/assets/map_tiles.png b/assets/map_tiles.png new file mode 100644 index 0000000000000000000000000000000000000000..5c610aaf994a04c52b67a80e61413dfa6857229d GIT binary patch literal 5991 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 Uzk1W)KhS|S?!Io9TzR5@16-Ae-T(jq literal 0 HcmV?d00001 diff --git a/meson.build b/meson.build index a2ee37e..03ada2e 100644 --- a/meson.build +++ b/meson.build @@ -170,7 +170,7 @@ executable('zedcaster', dependencies: dependencies) executable('icongen', - [ 'dbc.cpp', 'tools/icongen.cpp' ], + [ 'config.cpp', 'dbc.cpp', 'tools/icongen.cpp' ], cpp_args: cpp_args, link_args: link_args, override_options: exe_defaults, diff --git a/shiterator.hpp b/shiterator.hpp index a6541d2..dea7410 100644 --- a/shiterator.hpp +++ b/shiterator.hpp @@ -131,8 +131,9 @@ * I am horribly bad at trigonometry and graphics algorithms, so if you've got an idea to improve them * or find a bug shoot me an email at help@learncodethehardway.com. */ -namespace shiterator { using std::vector, std::queue, std::array; using - std::min, std::max, std::floor; +namespace shiterator { + using std::vector, std::queue, std::array; + using std::min, std::max, std::floor; template using BaseRow = vector; diff --git a/tools/icongen.cpp b/tools/icongen.cpp index 0070f67..d57f8de 100644 --- a/tools/icongen.cpp +++ b/tools/icongen.cpp @@ -3,60 +3,152 @@ #include #include #include "constants.hpp" +#include "config.hpp" +#include +#include "shiterator.hpp" +#include + +namespace fs = std::filesystem; +constexpr const int TILE_COUNT=10; + +using namespace shiterator; + +using MapRow = BaseRow; +using MapGrid = Base; + +struct MapTileBuilder { + unsigned int $font_size = 20; + sf::Glyph $glyph; + sf::Font $font{FONT_FILE_NAME}; + sf::Vector2u $size; + sf::Vector2u $image_size; + sf::RenderTexture $render; + sf::RenderTexture $temp_render; + + MapTileBuilder(size_t x, size_t y) : + $size(x, y), + $image_size($size.x * TILE_COUNT, $size.y * TILE_COUNT), + $render($image_size), + $temp_render($size) + { + $font.setSmooth(false); + $render.setSmooth(false); + } -int main() { - unsigned int font_size = 30; - sf::Vector2u size{32, 32}; + void best_size(wchar_t for_char) { + $font_size = 20; // reset the size + // fit the glyph in our box height + auto temp = $font.getGlyph(for_char, $font_size, false); + auto temp_size = $font_size; + + while(temp.textureRect.size.y < int($size.y)-1 + && temp.textureRect.size.x < int($size.x)-1) + { + $glyph = temp; + $font_size = temp_size; + + temp_size++; + temp = $font.getGlyph(for_char, temp_size, false); + } + } + + void save_image(std::string icon_path) { + fs::path out_path{icon_path}; + + if(fs::exists(out_path)) { + fs::remove(out_path); + } + + sf::Image out_img = $render.getTexture().copyToImage(); + + bool worked = out_img.saveToFile(out_path); + dbc::check(worked, "Failed to write screenshot.png"); + } + + + void run(MapGrid& map) { + sf::Vector2f cell_pos{0.0f,0.0f}; + + for(each_row_t it{map}; it.next();) { + // skip empty slots + if(map[it.y][it.x] == 0) continue; + cell_pos.x = it.x * $size.x; + cell_pos.y = it.y * $size.y; - sf::RenderTexture render{size}; - render.setSmooth(false); + wchar_t display_char = map[it.y][it.x]; + std::wstring content{display_char}; - sf::Font font{FONT_FILE_NAME}; - font.setSmooth(false); + best_size(display_char); - wchar_t display_char = 3848; - std::wstring content{display_char}; - sf::Text icon{font, content, font_size}; + sf::Text icon{$font, content, $font_size}; + icon.setFillColor({0, 0, 0, 255}); - icon.setFillColor({0, 0, 0, 255}); - render.draw(icon); - render.clear({0,0,0,0}); + $temp_render.draw(icon); + $temp_render.clear({0,0,0,0}); - // fit the glyph in our box height - auto glyph = font.getGlyph(content[0], font_size, false); + auto font_texture = $font.getTexture($font_size); + sf::Sprite sprite{font_texture, $glyph.textureRect}; + auto t_size = $glyph.textureRect.size; - while(glyph.textureRect.size.y < int(size.y)-1) { - font_size++; - glyph = font.getGlyph(content[0], font_size, false); + dbc::check(int($size.x - t_size.x) > 0, "font too big on x"); + dbc::check(int($size.y - t_size.y) > 0, "font too big on y"); + + sf::Vector2f center{ + (float($size.x) - float(t_size.x)) / 2.0f, + (float($size.y) - float(t_size.y)) / 2.0f}; + + sf::Vector2f scale{float($size.x) / float(t_size.x), float($size.y) / float(t_size.y)}; + + sprite.setScale(scale); + sprite.setPosition(cell_pos); + sprite.setColor({0, 0, 0, 255}); + + $render.draw(sprite); + } + + $render.display(); } +}; - auto font_texture = font.getTexture(font_size); - sf::Sprite sprite{font_texture, glyph.textureRect}; - auto t_size = glyph.textureRect.size; +void load_config(MapGrid& map, each_row_t& it, std::string path, + std::function finder) { + Config tiles(path); - dbc::check(int(size.x - t_size.x) > 0, "font too big on x"); - dbc::check(int(size.y - t_size.y) > 0, "font too big on y"); + for(auto [key, val] : tiles.json().items()) { + it.next(); + map[it.y][it.x] = finder(val); + } +} - sf::Vector2f center{ - (float(size.x) - float(t_size.x)) / 2.0f, - (float(size.y) - float(t_size.y)) / 2.0f}; +wchar_t component_display(nlohmann::json& val) { + auto& components = val["components"]; - sf::Vector2f scale{float(size.x) / float(t_size.x), float(size.y) / float(t_size.y)}; + for(auto& comp : components) { + if(comp["_type"] == "Tile") { + return comp["display"]; + } + } - fmt::println("scale={},{}; t_size={},{}; size={},{}", - scale.x, scale.y, t_size.x, t_size.y, size.x, size.y); + dbc::log("BAD CHAR"); + return L'!'; +} - sprite.setScale(scale); - sprite.setPosition({0,0}); - sprite.setColor({0, 0, 0, 255}); +int main() { + MapGrid map = make(TILE_COUNT, TILE_COUNT); + each_row_t it{map}; + + load_config(map, it, "./assets/tiles.json", [](nlohmann::json& val) -> wchar_t { + return val["display"]; + }); - render.draw(sprite); - render.display(); - sf::Image out_img = render.getTexture().copyToImage(); + load_config(map, it, "./assets/items.json", component_display); + load_config(map, it, "./assets/devices.json", component_display); + load_config(map, it, "./assets/enemies.json", component_display); - bool worked = out_img.saveToFile("./screenshot.png"); - dbc::check(worked, "Failed to write screenshot.png"); + MapTileBuilder builder(32, 32); + builder.run(map); + builder.save_image("./assets/map_tiles.png"); return 0; }