From 15a302d133dbfd6d736cf55aaa69e946a7261b70 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Thu, 21 Nov 2024 15:51:22 -0500 Subject: [PATCH] Renderer is now more standalone and doesn't try to protect against small maps, that's the GUI's job. --- Makefile | 2 +- gui.cpp | 16 +++++----- gui.hpp | 7 +++-- main.cpp | 2 ++ map.hpp | 8 ++--- panel.cpp | 4 ++- panel.hpp | 2 +- render.cpp | 70 +++++++++++++---------------------------- render.hpp | 25 ++++++++------- scratchpad/img2ansi.cpp | 18 ++++------- status.txt | 3 +- 11 files changed, 66 insertions(+), 91 deletions(-) diff --git a/Makefile b/Makefile index ed9318a..ff8c808 100644 --- a/Makefile +++ b/Makefile @@ -27,4 +27,4 @@ clean: meson compile --clean -C builddir debug: - gdb --nx -x .gdbinit builddir/img2ansi.exe + gdb --nx -x .gdbinit builddir/roguish.exe diff --git a/gui.cpp b/gui.cpp index 295f6d8..448dbb0 100644 --- a/gui.cpp +++ b/gui.cpp @@ -22,19 +22,20 @@ #include "render.hpp" #include "save.hpp" +const int MAX_FONT_SIZE = 140; +const int MIN_FONT_SIZE = 20; + using std::string; using namespace fmt; using namespace std::chrono_literals; using namespace ftxui; using namespace components; - GUI::GUI(DinkyECS::World &world, Map& game_map) : $game_map(game_map), $log({{"Welcome to the game!"}}), - $status_ui(SCREEN_X, SCREEN_Y, 0, 0), - $map_view(0, 0, GAME_MAP_POS, 0, true), - $view_port{0,0}, + $status_ui(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), + $map_view(GAME_MAP_POS, 0, 0, 0, true), $world(world), $sounds("./assets"), $renderer() @@ -49,10 +50,9 @@ GUI::GUI(DinkyECS::World &world, Map& game_map) : } void GUI::resize_map(int new_size) { - if($renderer.resize_grid(new_size, $view_port)) { + if($renderer.resize_grid(new_size, $map_view)) { // set canvas to best size - $canvas = Canvas($view_port.x * 2, $view_port.y * 4); - $map_view.resize($view_port.x, $view_port.y); + $canvas = Canvas($map_view.width * 2, $map_view.height * 4); } } @@ -66,7 +66,7 @@ void GUI::create_renderer() { auto player = $world.get_the(); $map_view.set_renderer(Renderer([&] { - System::draw_map($world, $game_map, $canvas, $view_port.x, $view_port.y); + System::draw_map($world, $game_map, $canvas, $map_view.width, $map_view.height); return canvas($canvas); })); diff --git a/gui.hpp b/gui.hpp index 38af59d..7eec6be 100644 --- a/gui.hpp +++ b/gui.hpp @@ -22,8 +22,8 @@ using std::string; using ftxui::Canvas, ftxui::Component, ftxui::Screen, ftxui::Button; -constexpr int SCREEN_X = 40; -constexpr int SCREEN_Y = 30; +constexpr int SCREEN_WIDTH = 40; +constexpr int SCREEN_HEIGHT = 30; struct ActionLog { std::deque messages; @@ -36,6 +36,8 @@ struct ActionLog { } }; +const int GAME_MAP_POS = 600; + class GUI { string $status_text = "NOT DEAD"; Canvas $canvas; @@ -44,7 +46,6 @@ class GUI { Panel $status_ui; Panel $map_view; bool $show_modal = false; - Point $view_port; Component $test_button; DinkyECS::World& $world; SoundManager $sounds; diff --git a/main.cpp b/main.cpp index 15f859d..ce5e9f1 100644 --- a/main.cpp +++ b/main.cpp @@ -53,6 +53,8 @@ void configure_world(DinkyECS::World &world, Map &game_map) { world.set(gold, {"$"}); } +const int GAME_MAP_X = 40; +const int GAME_MAP_Y = 40; int main(int argc, char *argv[]) { #if defined(_WIN64) || defined(_WIN32) diff --git a/map.hpp b/map.hpp index 0716555..f17505e 100644 --- a/map.hpp +++ b/map.hpp @@ -13,9 +13,6 @@ #define WALL_VALUE 1 #define SPACE_VALUE 0 -constexpr int GAME_MAP_X = 40; -constexpr int GAME_MAP_Y = 40; - struct Room { size_t x = 0; size_t y = 0; @@ -101,8 +98,9 @@ public: int center_x = int(around.x - view_x / 2); int center_y = int(around.y - view_y / 2); - size_t start_x = std::clamp(center_x, 0, high_x); - size_t start_y = std::clamp(center_y, 0, high_y); + // BUG: is clamp really the best thing here? this seems wrong. + size_t start_x = high_x > 0 ? std::clamp(center_x, 0, high_x) : 0; + size_t start_y = high_y > 0 ? std::clamp(center_y, 0, high_y) : 0; return {start_x, start_y}; } diff --git a/panel.cpp b/panel.cpp index 14f2f33..08fd79e 100644 --- a/panel.cpp +++ b/panel.cpp @@ -1,7 +1,9 @@ #include "panel.hpp" -void Panel::resize(int width, int height) { +void Panel::resize(int w, int h) { $dirty = true; + width = w; + height = h; $screen = Screen(width, height); } diff --git a/panel.hpp b/panel.hpp index 1aae1fb..68afed1 100644 --- a/panel.hpp +++ b/panel.hpp @@ -33,7 +33,7 @@ struct Panel { std::wstring_convert> $converter; std::wstring $screenout; - Panel(int width, int height, int x, int y, bool is_grid=false) : + Panel(int x, int y, int width, int height, bool is_grid=false) : x(x), y(y), width(width), diff --git a/render.cpp b/render.cpp index 8c03422..7b363fc 100644 --- a/render.cpp +++ b/render.cpp @@ -10,7 +10,7 @@ using namespace fmt; SFMLRender::SFMLRender() : - $window(sf::VideoMode(VIDEO_X,VIDEO_Y), "Roguish"), + $window(sf::VideoMode($config.video_x,$config.video_y), "Roguish"), $map_font_size(0), $line_spacing(0), $default_fg(color::LIGHT_MID), @@ -22,9 +22,9 @@ SFMLRender::SFMLRender() : $font.setSmooth(false); $ui_text.setFont($font); $ui_text.setPosition(0,0); - $ui_text.setCharacterSize(UI_FONT_SIZE); + $ui_text.setCharacterSize($config.ui_font_size); $ui_text.setFillColor(color::LIGHT_MID); - sf::Glyph glyph = $font.getGlyph(UI_BASE_CHAR, UI_FONT_SIZE, false); + sf::Glyph glyph = $font.getGlyph($config.ui_base_char, $config.ui_font_size, false); $ui_bounds = glyph.bounds; } @@ -43,47 +43,21 @@ sf::Sprite &SFMLRender::get_text_sprite(wchar_t tile) { return $sprites[tile]; } -inline bool base_glyph_check(sf::Font &font, sf::Glyph &base_glyph, Point &view_port, int &font_size, int new_size) { - auto glyph = font.getGlyph(BG_TILE, new_size, false); - int view_x = std::ceil((VIDEO_X - GAME_MAP_POS) / glyph.bounds.width); - int view_y = std::ceil(VIDEO_Y / glyph.bounds.height); - - // don't allow resizing beyond/below game map size - if(view_x <= GAME_MAP_X && view_y <= GAME_MAP_Y) { - // looks good, set 'em all - base_glyph = glyph; - view_port = {size_t(view_x), size_t(view_y)}; - font_size = new_size; - return true; - } else { - println("VIEW TOO BIG, view={},{} MAP={},{}", view_x, view_y, - GAME_MAP_X, GAME_MAP_Y); - return false; - } -} - - -bool SFMLRender::resize_grid(int new_size, Point &view_port) { - if($map_font_size == new_size || new_size < MIN_FONT_SIZE || new_size > MAX_FONT_SIZE) { - println("invalid map font size {}, =={}, min={}, max={}", - new_size, $map_font_size, MIN_FONT_SIZE, MAX_FONT_SIZE); - return false; - } else { - println("NEW SIZE SELECTED {}", new_size); - } - - if(base_glyph_check($font, $base_glyph, view_port, $map_font_size, new_size)) { - $sprites.clear(); // need to reset the sprites for the new size - $line_spacing = $font.getLineSpacing($map_font_size); - $bg_sprite = get_text_sprite(BG_TILE); - $bg_bounds = $bg_sprite.getLocalBounds(); - return true; - } else { - println("BASE GLYPH FAILED!"); - // something else here - return false; - } +bool SFMLRender::resize_grid(int new_size, Panel &panel_out) { + auto glyph = $font.getGlyph($config.bg_tile, new_size, false); + int view_x = std::ceil(($config.video_x - panel_out.x) / glyph.bounds.width); + int view_y = std::ceil(($config.video_y - panel_out.y) / glyph.bounds.height); + + // looks good, set 'em all + $base_glyph = glyph; + $map_font_size = new_size; + $sprites.clear(); // need to reset the sprites for the new size + $line_spacing = $font.getLineSpacing($map_font_size); + $bg_sprite = get_text_sprite($config.bg_tile); + $bg_bounds = $bg_sprite.getLocalBounds(); + panel_out.resize(view_x, view_y); + return true; } inline void configure_tile(const sf::Sprite &sprite, sf::FloatRect &sp_bounds, sf::FloatRect bg_bounds, float &width_delta, float &height_delta) { @@ -143,7 +117,7 @@ void SFMLRender::render_grid(const std::wstring &text, float x, float y) { inline sf::FloatRect draw_chunk(sf::RenderWindow& window, sf::FloatRect ui_bounds, sf::Text& text, sf::Color default_bg, - sf::Color bgcolor, float x, float y, std::wstring &out) + sf::Color bgcolor, int bg_box_offset, float x, float y, std::wstring &out) { text.setString(out); text.setPosition({x, y}); @@ -152,7 +126,7 @@ inline sf::FloatRect draw_chunk(sf::RenderWindow& window, if(default_bg != bgcolor) { sf::RectangleShape backing({bounds.width, bounds.height}); backing.setFillColor(bgcolor); - backing.setPosition({bounds.left, bounds.top + BG_BOX_OFFSET}); + backing.setPosition({bounds.left, bounds.top + bg_box_offset}); window.draw(backing); } @@ -175,7 +149,7 @@ void SFMLRender::render_text(const std::wstring &text, sf::Color default_bg, flo if(out.size() > 0 ) { auto bounds = draw_chunk($window, $ui_bounds, $ui_text, - default_bg, cur_bg, x, y, out); + default_bg, cur_bg, $config.bg_box_offset, x, y, out); x += bounds.width; } cur_bg = bg; @@ -189,7 +163,7 @@ void SFMLRender::render_text(const std::wstring &text, sf::Color default_bg, flo if(out.size() > 0) { bounds = draw_chunk($window, $ui_bounds, - $ui_text, default_bg, cur_bg, x, y, out); + $ui_text, default_bg, cur_bg, $config.bg_box_offset, x, y, out); } else { bounds = $ui_text.getLocalBounds(); } @@ -206,7 +180,7 @@ void SFMLRender::render_text(const std::wstring &text, sf::Color default_bg, flo ); if(out.size() > 0) { - draw_chunk($window, $ui_bounds, $ui_text, default_bg, cur_bg, x, y, out); + draw_chunk($window, $ui_bounds, $ui_text, default_bg, cur_bg, $config.bg_box_offset, x, y, out); } } diff --git a/render.hpp b/render.hpp index 67200d0..c22c410 100644 --- a/render.hpp +++ b/render.hpp @@ -13,18 +13,21 @@ using ftxui::Canvas, ftxui::Screen; -const int VIDEO_X = 1600; -const int VIDEO_Y = 900; -const int MIN_FONT_SIZE = 20; -const int MAX_FONT_SIZE = 140; -const int GAME_MAP_POS = 600; -const int UI_FONT_SIZE=30; -const int BASE_MAP_FONT_SIZE=90; -const wchar_t BG_TILE = L'█'; -const wchar_t UI_BASE_CHAR = L'█'; -const int BG_BOX_OFFSET=5; + +struct RenderConfig { + int video_x = 1600; + int video_y = 900; + int ui_font_size=30; + int base_map_font_size=90; + wchar_t bg_tile = L'█'; + wchar_t ui_base_char = L'█'; + int bg_box_offset=5; + int game_map_x=40; + int game_map_y=40; +}; struct SFMLRender { + RenderConfig $config; sf::RenderWindow $window; int $map_font_size; float $line_spacing; @@ -47,7 +50,7 @@ struct SFMLRender { SFMLRender(SFMLRender &other) = delete; sf::Sprite &get_text_sprite(wchar_t tile); - bool resize_grid(int new_size, Point &view_port); + bool resize_grid(int new_size, Panel &panel_out); void render_grid(const std::wstring &text, float x, float y); void render_text(const std::wstring &text, sf::Color bgcolor, float x, float y); diff --git a/scratchpad/img2ansi.cpp b/scratchpad/img2ansi.cpp index 1afbf9d..c1d700b 100644 --- a/scratchpad/img2ansi.cpp +++ b/scratchpad/img2ansi.cpp @@ -81,11 +81,10 @@ int main(int argc, char *argv[]) { // divide the image into cells auto size = image.getSize(); - const int cell = 10; + const int cell = 3; // create a grid panel to hold the cells - Panel panel(0, 0, GAME_MAP_POS, 0, true); - Point view_port{0,0}; + Panel panel(0, 0, 0, 0, true); println("IMAGE SIZE {},{}", size.x, size.y); RGBColor avg{0,0,0}; @@ -124,16 +123,11 @@ int main(int argc, char *argv[]) { SFMLRender renderer; - // NEED TO RESIZE FOR IT TO SHOW - // this shows that I need more refinement on the renderer - // for example, this won't let me do arbitrary resize and - // is still locked to the map, but I need arbitrary for the - // scenes - if(renderer.resize_grid(50, view_port)) { - println("RESIZED: {},{}", view_port.x, view_port.y); + + if(renderer.resize_grid(10, panel)) { + println("RESIZED: {},{}", panel.width, panel.height); // set canvas to best size - drawing = Canvas(view_port.x * 2, view_port.y * 4); - panel.resize(view_port.x, view_port.y); + drawing = Canvas(panel.width * 2, panel.height * 4); } panel.set_renderer(Renderer([&]{ diff --git a/status.txt b/status.txt index 8de28f8..fbd31ec 100644 --- a/status.txt +++ b/status.txt @@ -1,7 +1,8 @@ TODAY'S GOAL: -* panels and everything except renderer should use character coodinates * Image -> Text converter. +* Renderer needs to not have fixed setting for its size from the map. +* Refactor out GAME_MAP_* to be a parameter. TODO: