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 0000000..5c610aa Binary files /dev/null and b/assets/map_tiles.png differ 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; }