A bit more caching and optimization then determine how to center glyphs in the center of the background if it fits.

main
Zed A. Shaw 11 months ago
parent 9083582420
commit e57a13846f
  1. 89
      gui.cpp
  2. 4
      gui.hpp

@ -55,7 +55,9 @@ GUI::GUI() :
$window(sf::VideoMode(VIDEO_X,VIDEO_Y), "Roguish"), $window(sf::VideoMode(VIDEO_X,VIDEO_Y), "Roguish"),
$screen(SCREEN_X, SCREEN_Y), $screen(SCREEN_X, SCREEN_Y),
$map_screen(0,0), $map_screen(0,0),
$map_font_size(BASE_MAP_FONT_SIZE) $view_port{0,0},
$map_font_size(BASE_MAP_FONT_SIZE),
$line_spacing(0)
{ {
$font.loadFromFile("./assets/text.otf"); $font.loadFromFile("./assets/text.otf");
resize_map(BASE_MAP_FONT_SIZE); resize_map(BASE_MAP_FONT_SIZE);
@ -131,7 +133,6 @@ bool GUI::handle_events() {
sf::Sprite &GUI::get_text_sprite(wchar_t tile) { sf::Sprite &GUI::get_text_sprite(wchar_t tile) {
if(!$sprites.contains(tile)) { if(!$sprites.contains(tile)) {
$sprites.clear();
sf::Glyph glyph = $font.getGlyph(tile, $map_font_size, false); sf::Glyph glyph = $font.getGlyph(tile, $map_font_size, false);
// WARNING! we actually have to do this here because SFML caches // WARNING! we actually have to do this here because SFML caches
// the glyphs on the font texture, so this gets loaded each time // the glyphs on the font texture, so this gets loaded each time
@ -154,9 +155,11 @@ void GUI::run_systems() {
void GUI::resize_map(int new_size) { void GUI::resize_map(int new_size) {
if(MIN_FONT_SIZE < new_size && new_size < MAX_FONT_SIZE) { if(MIN_FONT_SIZE < new_size && new_size < MAX_FONT_SIZE) {
$sprites.clear(); // need to reset the sprites for the new size
$map_font_size = new_size; $map_font_size = new_size;
sf::Glyph base_glyph = $font.getGlyph(L'', $map_font_size, false); $base_glyph = $font.getGlyph(L'', $map_font_size, false);
auto bounds = base_glyph.bounds; auto bounds = $base_glyph.bounds;
$line_spacing = $font.getLineSpacing($map_font_size);
$view_port = { $view_port = {
size_t(std::ceil((VIDEO_X - GAME_MAP_POS) / bounds.width)), size_t(std::ceil((VIDEO_X - GAME_MAP_POS) / bounds.width)),
size_t(std::ceil(VIDEO_Y / bounds.height)) size_t(std::ceil(VIDEO_Y / bounds.height))
@ -179,48 +182,64 @@ void GUI::draw_screen(bool clear, float map_off_x, float map_off_y) {
float y = 0.0f; float y = 0.0f;
float x = GAME_MAP_POS; float x = GAME_MAP_POS;
const float line_spacing = $font.getLineSpacing($map_font_size); // make a copy so we don't modify the cached one
sf::Glyph base_glyph = $font.getGlyph(L'', $map_font_size, false);
auto bg_sprite = get_text_sprite(L''); auto bg_sprite = get_text_sprite(L'');
auto bg_bounds = bg_sprite.getLocalBounds();
bg_sprite.setColor(sf::Color(20,20,20)); bg_sprite.setColor(sf::Color(20,20,20));
auto add_sprite = get_text_sprite(L'!'); auto add_sprite = get_text_sprite(L'!');
bool has_add = false; bool has_add = false;
for(size_t i = 0; i < map_screen_utf8.size(); i++) { for(size_t i = 0; i < map_screen_utf8.size(); i++) {
wchar_t tile = map_screen_utf8[i]; wchar_t tile = map_screen_utf8[i];
sf::Sprite &sprite = get_text_sprite(tile);
sprite.setPosition({x, y}); if(tile == L'\n') {
bg_sprite.setPosition({x, y}); // don't bother processing newlines, just skip
y += $line_spacing;
if(tile == L'') {
sprite.setColor(sf::Color(80,80,80));
} else if(tile == L'') {
sprite.setColor(sf::Color::Blue);
} else if(tile == L'Ω') {
sprite.setColor(sf::Color::Red);
add_sprite.setColor(sf::Color::Red);
add_sprite.setPosition({x-3,y-3});
has_add = true;
} else if(tile == L'#') {
sprite.setColor(sf::Color(5,5,5));
} else if(tile == L'\r') {
continue; // skip these, just windows junk
} else if(tile == L'\n') {
// newline
y += line_spacing;
x = GAME_MAP_POS; x = GAME_MAP_POS;
continue; } else if(tile == L'\r') {
continue; // skip these, just windows junk
} else { } else {
sprite.setColor(color(Value::MID)); // it's a visual cell
} bg_sprite.setPosition({x, y});
sf::Sprite &sprite = get_text_sprite(tile);
// should look into caching all this instead of calcing it each time
auto sp_bounds = sprite.getLocalBounds();
// calculate where to center the sprite, but only if it's smaller
auto width_delta = bg_bounds.width > sp_bounds.width ? (bg_bounds.width - sp_bounds.width) / 2 : 0;
auto height_delta = bg_bounds.height > sp_bounds.width ? (bg_bounds.height - sp_bounds.height) / 2 : 0;
// TODO: need to center it inside the bg_sprite
sprite.setPosition({x+width_delta, y+height_delta});
if(tile == L'') {
sprite.setColor(sf::Color(80,80,80));
} else if(tile == L'') {
sprite.setColor(sf::Color::Blue);
} else if(tile == L'Ω') {
sprite.setColor(sf::Color::Red);
// HACK: just playing with adding multiple characters for drawing
add_sprite.setColor(sf::Color::Red);
add_sprite.setPosition({x-3,y-3});
has_add = true;
} else if(tile == L'#') {
sprite.setColor(sf::Color(5,5,5));
} else {
sprite.setColor(color(Value::MID));
}
$window.draw(bg_sprite); // now draw the background sprite and sprite
$window.draw(sprite); // TODO: this can become a standard sprite description
if(has_add) { $window.draw(bg_sprite);
$window.draw(add_sprite); $window.draw(sprite);
has_add = false; if(has_add) {
$window.draw(add_sprite);
has_add = false;
}
// next cell
x += $base_glyph.advance;
} }
x += base_glyph.advance;
} }
$window.display(); $window.display();

@ -52,8 +52,10 @@ class GUI {
DinkyECS::World $world; DinkyECS::World $world;
sf::Texture $font_texture; sf::Texture $font_texture;
std::unordered_map<wchar_t, sf::Sprite> $sprites; std::unordered_map<wchar_t, sf::Sprite> $sprites;
Point $view_port = {0,0}; Point $view_port;
int $map_font_size; int $map_font_size;
sf::Glyph $base_glyph;
float $line_spacing;
public: public:
GUI(); GUI();