Renderer is now more standalone and doesn't try to protect against small maps, that's the GUI's job.
This commit is contained in:
parent
19b8bf1850
commit
15a302d133
11 changed files with 65 additions and 90 deletions
2
Makefile
2
Makefile
|
@ -27,4 +27,4 @@ clean:
|
||||||
meson compile --clean -C builddir
|
meson compile --clean -C builddir
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
gdb --nx -x .gdbinit builddir/img2ansi.exe
|
gdb --nx -x .gdbinit builddir/roguish.exe
|
||||||
|
|
16
gui.cpp
16
gui.cpp
|
@ -22,19 +22,20 @@
|
||||||
#include "render.hpp"
|
#include "render.hpp"
|
||||||
#include "save.hpp"
|
#include "save.hpp"
|
||||||
|
|
||||||
|
const int MAX_FONT_SIZE = 140;
|
||||||
|
const int MIN_FONT_SIZE = 20;
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using namespace fmt;
|
using namespace fmt;
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
using namespace components;
|
using namespace components;
|
||||||
|
|
||||||
|
|
||||||
GUI::GUI(DinkyECS::World &world, Map& game_map) :
|
GUI::GUI(DinkyECS::World &world, Map& game_map) :
|
||||||
$game_map(game_map),
|
$game_map(game_map),
|
||||||
$log({{"Welcome to the game!"}}),
|
$log({{"Welcome to the game!"}}),
|
||||||
$status_ui(SCREEN_X, SCREEN_Y, 0, 0),
|
$status_ui(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT),
|
||||||
$map_view(0, 0, GAME_MAP_POS, 0, true),
|
$map_view(GAME_MAP_POS, 0, 0, 0, true),
|
||||||
$view_port{0,0},
|
|
||||||
$world(world),
|
$world(world),
|
||||||
$sounds("./assets"),
|
$sounds("./assets"),
|
||||||
$renderer()
|
$renderer()
|
||||||
|
@ -49,10 +50,9 @@ GUI::GUI(DinkyECS::World &world, Map& game_map) :
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI::resize_map(int new_size) {
|
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
|
// set canvas to best size
|
||||||
$canvas = Canvas($view_port.x * 2, $view_port.y * 4);
|
$canvas = Canvas($map_view.width * 2, $map_view.height * 4);
|
||||||
$map_view.resize($view_port.x, $view_port.y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ void GUI::create_renderer() {
|
||||||
auto player = $world.get_the<Player>();
|
auto player = $world.get_the<Player>();
|
||||||
|
|
||||||
$map_view.set_renderer(Renderer([&] {
|
$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);
|
return canvas($canvas);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
7
gui.hpp
7
gui.hpp
|
@ -22,8 +22,8 @@
|
||||||
using std::string;
|
using std::string;
|
||||||
using ftxui::Canvas, ftxui::Component, ftxui::Screen, ftxui::Button;
|
using ftxui::Canvas, ftxui::Component, ftxui::Screen, ftxui::Button;
|
||||||
|
|
||||||
constexpr int SCREEN_X = 40;
|
constexpr int SCREEN_WIDTH = 40;
|
||||||
constexpr int SCREEN_Y = 30;
|
constexpr int SCREEN_HEIGHT = 30;
|
||||||
|
|
||||||
struct ActionLog {
|
struct ActionLog {
|
||||||
std::deque<std::string> messages;
|
std::deque<std::string> messages;
|
||||||
|
@ -36,6 +36,8 @@ struct ActionLog {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const int GAME_MAP_POS = 600;
|
||||||
|
|
||||||
class GUI {
|
class GUI {
|
||||||
string $status_text = "NOT DEAD";
|
string $status_text = "NOT DEAD";
|
||||||
Canvas $canvas;
|
Canvas $canvas;
|
||||||
|
@ -44,7 +46,6 @@ class GUI {
|
||||||
Panel $status_ui;
|
Panel $status_ui;
|
||||||
Panel $map_view;
|
Panel $map_view;
|
||||||
bool $show_modal = false;
|
bool $show_modal = false;
|
||||||
Point $view_port;
|
|
||||||
Component $test_button;
|
Component $test_button;
|
||||||
DinkyECS::World& $world;
|
DinkyECS::World& $world;
|
||||||
SoundManager $sounds;
|
SoundManager $sounds;
|
||||||
|
|
2
main.cpp
2
main.cpp
|
@ -53,6 +53,8 @@ void configure_world(DinkyECS::World &world, Map &game_map) {
|
||||||
world.set<Tile>(gold, {"$"});
|
world.set<Tile>(gold, {"$"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int GAME_MAP_X = 40;
|
||||||
|
const int GAME_MAP_Y = 40;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
#if defined(_WIN64) || defined(_WIN32)
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
|
|
8
map.hpp
8
map.hpp
|
@ -13,9 +13,6 @@
|
||||||
#define WALL_VALUE 1
|
#define WALL_VALUE 1
|
||||||
#define SPACE_VALUE 0
|
#define SPACE_VALUE 0
|
||||||
|
|
||||||
constexpr int GAME_MAP_X = 40;
|
|
||||||
constexpr int GAME_MAP_Y = 40;
|
|
||||||
|
|
||||||
struct Room {
|
struct Room {
|
||||||
size_t x = 0;
|
size_t x = 0;
|
||||||
size_t y = 0;
|
size_t y = 0;
|
||||||
|
@ -101,8 +98,9 @@ public:
|
||||||
int center_x = int(around.x - view_x / 2);
|
int center_x = int(around.x - view_x / 2);
|
||||||
int center_y = int(around.y - view_y / 2);
|
int center_y = int(around.y - view_y / 2);
|
||||||
|
|
||||||
size_t start_x = std::clamp(center_x, 0, high_x);
|
// BUG: is clamp really the best thing here? this seems wrong.
|
||||||
size_t start_y = std::clamp(center_y, 0, high_y);
|
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};
|
return {start_x, start_y};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#include "panel.hpp"
|
#include "panel.hpp"
|
||||||
|
|
||||||
void Panel::resize(int width, int height) {
|
void Panel::resize(int w, int h) {
|
||||||
$dirty = true;
|
$dirty = true;
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
$screen = Screen(width, height);
|
$screen = Screen(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ struct Panel {
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> $converter;
|
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> $converter;
|
||||||
std::wstring $screenout;
|
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),
|
x(x),
|
||||||
y(y),
|
y(y),
|
||||||
width(width),
|
width(width),
|
||||||
|
|
58
render.cpp
58
render.cpp
|
@ -10,7 +10,7 @@
|
||||||
using namespace fmt;
|
using namespace fmt;
|
||||||
|
|
||||||
SFMLRender::SFMLRender() :
|
SFMLRender::SFMLRender() :
|
||||||
$window(sf::VideoMode(VIDEO_X,VIDEO_Y), "Roguish"),
|
$window(sf::VideoMode($config.video_x,$config.video_y), "Roguish"),
|
||||||
$map_font_size(0),
|
$map_font_size(0),
|
||||||
$line_spacing(0),
|
$line_spacing(0),
|
||||||
$default_fg(color::LIGHT_MID),
|
$default_fg(color::LIGHT_MID),
|
||||||
|
@ -22,9 +22,9 @@ SFMLRender::SFMLRender() :
|
||||||
$font.setSmooth(false);
|
$font.setSmooth(false);
|
||||||
$ui_text.setFont($font);
|
$ui_text.setFont($font);
|
||||||
$ui_text.setPosition(0,0);
|
$ui_text.setPosition(0,0);
|
||||||
$ui_text.setCharacterSize(UI_FONT_SIZE);
|
$ui_text.setCharacterSize($config.ui_font_size);
|
||||||
$ui_text.setFillColor(color::LIGHT_MID);
|
$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;
|
$ui_bounds = glyph.bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,47 +43,21 @@ sf::Sprite &SFMLRender::get_text_sprite(wchar_t tile) {
|
||||||
return $sprites[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);
|
bool SFMLRender::resize_grid(int new_size, Panel &panel_out) {
|
||||||
int view_y = std::ceil(VIDEO_Y / glyph.bounds.height);
|
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);
|
||||||
|
|
||||||
// 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
|
// looks good, set 'em all
|
||||||
base_glyph = glyph;
|
$base_glyph = glyph;
|
||||||
view_port = {size_t(view_x), size_t(view_y)};
|
$map_font_size = new_size;
|
||||||
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
|
$sprites.clear(); // need to reset the sprites for the new size
|
||||||
$line_spacing = $font.getLineSpacing($map_font_size);
|
$line_spacing = $font.getLineSpacing($map_font_size);
|
||||||
$bg_sprite = get_text_sprite(BG_TILE);
|
$bg_sprite = get_text_sprite($config.bg_tile);
|
||||||
$bg_bounds = $bg_sprite.getLocalBounds();
|
$bg_bounds = $bg_sprite.getLocalBounds();
|
||||||
|
panel_out.resize(view_x, view_y);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
println("BASE GLYPH FAILED!");
|
|
||||||
// something else here
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void configure_tile(const sf::Sprite &sprite, sf::FloatRect &sp_bounds, sf::FloatRect bg_bounds, float &width_delta, float &height_delta) {
|
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,
|
inline sf::FloatRect draw_chunk(sf::RenderWindow& window,
|
||||||
sf::FloatRect ui_bounds, sf::Text& text, sf::Color default_bg,
|
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.setString(out);
|
||||||
text.setPosition({x, y});
|
text.setPosition({x, y});
|
||||||
|
@ -152,7 +126,7 @@ inline sf::FloatRect draw_chunk(sf::RenderWindow& window,
|
||||||
if(default_bg != bgcolor) {
|
if(default_bg != bgcolor) {
|
||||||
sf::RectangleShape backing({bounds.width, bounds.height});
|
sf::RectangleShape backing({bounds.width, bounds.height});
|
||||||
backing.setFillColor(bgcolor);
|
backing.setFillColor(bgcolor);
|
||||||
backing.setPosition({bounds.left, bounds.top + BG_BOX_OFFSET});
|
backing.setPosition({bounds.left, bounds.top + bg_box_offset});
|
||||||
window.draw(backing);
|
window.draw(backing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +149,7 @@ void SFMLRender::render_text(const std::wstring &text, sf::Color default_bg, flo
|
||||||
if(out.size() > 0 ) {
|
if(out.size() > 0 ) {
|
||||||
auto bounds = draw_chunk($window,
|
auto bounds = draw_chunk($window,
|
||||||
$ui_bounds, $ui_text,
|
$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;
|
x += bounds.width;
|
||||||
}
|
}
|
||||||
cur_bg = bg;
|
cur_bg = bg;
|
||||||
|
@ -189,7 +163,7 @@ void SFMLRender::render_text(const std::wstring &text, sf::Color default_bg, flo
|
||||||
|
|
||||||
if(out.size() > 0) {
|
if(out.size() > 0) {
|
||||||
bounds = draw_chunk($window, $ui_bounds,
|
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 {
|
} else {
|
||||||
bounds = $ui_text.getLocalBounds();
|
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) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
25
render.hpp
25
render.hpp
|
@ -13,18 +13,21 @@
|
||||||
|
|
||||||
using ftxui::Canvas, ftxui::Screen;
|
using ftxui::Canvas, ftxui::Screen;
|
||||||
|
|
||||||
const int VIDEO_X = 1600;
|
|
||||||
const int VIDEO_Y = 900;
|
struct RenderConfig {
|
||||||
const int MIN_FONT_SIZE = 20;
|
int video_x = 1600;
|
||||||
const int MAX_FONT_SIZE = 140;
|
int video_y = 900;
|
||||||
const int GAME_MAP_POS = 600;
|
int ui_font_size=30;
|
||||||
const int UI_FONT_SIZE=30;
|
int base_map_font_size=90;
|
||||||
const int BASE_MAP_FONT_SIZE=90;
|
wchar_t bg_tile = L'█';
|
||||||
const wchar_t BG_TILE = L'█';
|
wchar_t ui_base_char = L'█';
|
||||||
const wchar_t UI_BASE_CHAR = L'█';
|
int bg_box_offset=5;
|
||||||
const int BG_BOX_OFFSET=5;
|
int game_map_x=40;
|
||||||
|
int game_map_y=40;
|
||||||
|
};
|
||||||
|
|
||||||
struct SFMLRender {
|
struct SFMLRender {
|
||||||
|
RenderConfig $config;
|
||||||
sf::RenderWindow $window;
|
sf::RenderWindow $window;
|
||||||
int $map_font_size;
|
int $map_font_size;
|
||||||
float $line_spacing;
|
float $line_spacing;
|
||||||
|
@ -47,7 +50,7 @@ struct SFMLRender {
|
||||||
SFMLRender(SFMLRender &other) = delete;
|
SFMLRender(SFMLRender &other) = delete;
|
||||||
|
|
||||||
sf::Sprite &get_text_sprite(wchar_t tile);
|
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_grid(const std::wstring &text, float x, float y);
|
||||||
void render_text(const std::wstring &text, sf::Color bgcolor, float x, float y);
|
void render_text(const std::wstring &text, sf::Color bgcolor, float x, float y);
|
||||||
|
|
||||||
|
|
|
@ -81,11 +81,10 @@ int main(int argc, char *argv[]) {
|
||||||
// divide the image into cells
|
// divide the image into cells
|
||||||
auto size = image.getSize();
|
auto size = image.getSize();
|
||||||
|
|
||||||
const int cell = 10;
|
const int cell = 3;
|
||||||
|
|
||||||
// create a grid panel to hold the cells
|
// create a grid panel to hold the cells
|
||||||
Panel panel(0, 0, GAME_MAP_POS, 0, true);
|
Panel panel(0, 0, 0, 0, true);
|
||||||
Point view_port{0,0};
|
|
||||||
|
|
||||||
println("IMAGE SIZE {},{}", size.x, size.y);
|
println("IMAGE SIZE {},{}", size.x, size.y);
|
||||||
RGBColor avg{0,0,0};
|
RGBColor avg{0,0,0};
|
||||||
|
@ -124,16 +123,11 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
|
||||||
SFMLRender renderer;
|
SFMLRender renderer;
|
||||||
// NEED TO RESIZE FOR IT TO SHOW
|
|
||||||
// this shows that I need more refinement on the renderer
|
if(renderer.resize_grid(10, panel)) {
|
||||||
// for example, this won't let me do arbitrary resize and
|
println("RESIZED: {},{}", panel.width, panel.height);
|
||||||
// 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);
|
|
||||||
// set canvas to best size
|
// set canvas to best size
|
||||||
drawing = Canvas(view_port.x * 2, view_port.y * 4);
|
drawing = Canvas(panel.width * 2, panel.height * 4);
|
||||||
panel.resize(view_port.x, view_port.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.set_renderer(Renderer([&]{
|
panel.set_renderer(Renderer([&]{
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
TODAY'S GOAL:
|
TODAY'S GOAL:
|
||||||
|
|
||||||
* panels and everything except renderer should use character coodinates
|
|
||||||
* Image -> Text converter.
|
* 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:
|
TODO:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue