Icons now work way better and don't have the the 'Rayview cuts icons' bug. It actually was a bug in the lel-guecs Sprite class that was using the TextureRect from the source sprite. Now its initialized with the framesize from the .json. This also uses the new guecs::Icon, but I have to fix that as it doesn't scale correctly. Closes #2.

master
Zed A. Shaw 4 days ago
parent b311713064
commit ff7111b006
  1. 10
      assets/config.json
  2. 12
      assets/icons.json
  3. BIN
      assets/icons/healing_potion_small.png
  4. BIN
      assets/icons/healing_potion_small_ICON.png
  5. BIN
      assets/icons/torch_crappy_ICON.png
  6. BIN
      assets/icons/torch_horizontal_floor.png
  7. 13
      backend.cpp
  8. 5
      backend.hpp
  9. 6
      gui/boss_fight_ui.cpp
  10. 1
      gui/fsm.cpp
  11. 6
      gui/guecstra.cpp
  12. 4
      gui/loot_ui.cpp
  13. 9
      gui/map_view.cpp
  14. 1
      gui/map_view.hpp
  15. 2
      gui/ritual_ui.cpp
  16. 4
      gui/status_ui.cpp
  17. 2
      raycaster.cpp
  18. 2
      tests/animation.cpp
  19. 2
      tests/textures.cpp
  20. 56
      textures.cpp
  21. 8
      textures.hpp
  22. 2
      tools/fragviewer.cpp

@ -80,11 +80,6 @@
"frame_width": 256, "frame_width": 256,
"frame_height": 256 "frame_height": 256
}, },
"torch_horizontal_floor_ICON":
{"path": "assets/icons/torch_crappy_ICON.png",
"frame_width": 128,
"frame_height": 128
},
"peasant_girl": "peasant_girl":
{"path": "assets/sprites/peasant_girl_2.png", {"path": "assets/sprites/peasant_girl_2.png",
"frame_width": 256, "frame_width": 256,
@ -100,11 +95,6 @@
"frame_width": 256, "frame_width": 256,
"frame_height": 256 "frame_height": 256
}, },
"healing_potion_small_ICON":
{"path": "assets/icons/healing_potion_small_ICON.png",
"frame_width": 128,
"frame_height": 128
},
"well_down": "well_down":
{"path": "assets/sprites/well_down.png", {"path": "assets/sprites/well_down.png",
"frame_width": 256, "frame_width": 256,

@ -0,0 +1,12 @@
{
"healing_potion_small":
{"path": "assets/icons/healing_potion_small.png",
"frame_width": 96,
"frame_height": 96
},
"torch_horizontal_floor":
{"path": "assets/icons/torch_horizontal_floor.png",
"frame_width": 96,
"frame_height": 96
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

@ -8,9 +8,14 @@
namespace sfml { namespace sfml {
using namespace nlohmann; using namespace nlohmann;
guecs::SpriteTexture Backend::texture_get(const string& name) { guecs::SpriteTexture Backend::get_sprite(const string& name) {
auto sp = textures::get(name); auto sp = textures::get_sprite(name);
return {sp.sprite, sp.texture}; return {sp.sprite, sp.texture, sp.frame_size};
}
guecs::SpriteTexture Backend::get_icon(const string& name) {
auto sp = textures::get_icon(name);
return {sp.sprite, sp.texture, sp.frame_size};
} }
Backend::Backend() { Backend::Backend() {
@ -27,7 +32,7 @@ namespace sfml {
sound::stop(name); sound::stop(name);
} }
std::shared_ptr<sf::Shader> Backend::shader_get(const std::string& name) { std::shared_ptr<sf::Shader> Backend::get_shader(const std::string& name) {
return shaders::get(name); return shaders::get(name);
} }

@ -9,10 +9,11 @@ namespace sfml {
public: public:
Backend(); Backend();
guecs::SpriteTexture texture_get(const string& name); guecs::SpriteTexture get_sprite(const string& name);
guecs::SpriteTexture get_icon(const string& name);
void sound_play(const string& name); void sound_play(const string& name);
void sound_stop(const string& name); void sound_stop(const string& name);
std::shared_ptr<sf::Shader> shader_get(const std::string& name); std::shared_ptr<sf::Shader> get_shader(const std::string& name);
bool shader_updated(); bool shader_updated();
guecs::Theme theme(); guecs::Theme theme();
}; };

@ -35,7 +35,7 @@ namespace gui {
$animation = $world->get<components::Animation>($boss_id); $animation = $world->get<components::Animation>($boss_id);
$animation.frame_width = $sprite_config.width; $animation.frame_width = $sprite_config.width;
$boss_image = textures::get($sprite_config.name); $boss_image = textures::get_sprite($sprite_config.name);
sf::IntRect frame_rect{{0,0},{$sprite_config.width,$sprite_config.height}}; sf::IntRect frame_rect{{0,0},{$sprite_config.width,$sprite_config.height}};
$boss_image.sprite->setTextureRect(frame_rect); $boss_image.sprite->setTextureRect(frame_rect);
$boss_image.sprite->setScale({$sprite_config.scale, $sprite_config.scale}); $boss_image.sprite->setScale({$sprite_config.scale, $sprite_config.scale});
@ -52,13 +52,13 @@ namespace gui {
void BossFightUI::configure_background() { void BossFightUI::configure_background() {
auto& boss = $world->get<components::BossFight>($boss_id); auto& boss = $world->get<components::BossFight>($boss_id);
$boss_background = textures::get(boss.background); $boss_background = textures::get_sprite(boss.background);
$boss_background.sprite->setPosition({BOSS_VIEW_X, BOSS_VIEW_Y}); $boss_background.sprite->setPosition({BOSS_VIEW_X, BOSS_VIEW_Y});
$status.set<Background>($status.MAIN, {$status.$parser}); $status.set<Background>($status.MAIN, {$status.$parser});
if(boss.stage) { if(boss.stage) {
$boss_has_stage = true; $boss_has_stage = true;
$boss_stage = textures::get(*boss.stage); $boss_stage = textures::get_sprite(*boss.stage);
$boss_stage.sprite->setPosition({BOSS_VIEW_X, BOSS_VIEW_Y}); $boss_stage.sprite->setPosition({BOSS_VIEW_X, BOSS_VIEW_Y});
} }
} }

@ -347,7 +347,6 @@ namespace gui {
if(!sound::playing("ambient_1")) sound::play("ambient_1", true); if(!sound::playing("ambient_1")) sound::play("ambient_1", true);
$debug_ui.debug(); $debug_ui.debug();
shaders::reload(); shaders::reload();
$map_ui.save_map($main_ui.$compass_dir);
break; break;
case KEY::O: case KEY::O:
autowalking = true; autowalking = true;

@ -21,11 +21,9 @@ namespace guecs {
} }
void GrabSource::setSprite(guecs::UI& gui, guecs::Entity gui_id) { void GrabSource::setSprite(guecs::UI& gui, guecs::Entity gui_id) {
dbc::check(gui.has<guecs::Sprite>(gui_id), "GrabSource given sprite gui_id that doesn't exist"); dbc::check(gui.has<guecs::Icon>(gui_id), "GrabSource given sprite gui_id that doesn't exist");
fmt::println("> Grabsource Set sprite entity {}", world_entity); auto& sp = gui.get<guecs::Icon>(gui_id);
auto& sp = gui.get<guecs::Sprite>(gui_id);
sprite = sp.sprite; sprite = sp.sprite;
} }

@ -75,7 +75,7 @@ namespace gui {
dbc::check($level.world->has<components::Sprite>(item), dbc::check($level.world->has<components::Sprite>(item),
"item in inventory UI doesn't exist in world. New level?"); "item in inventory UI doesn't exist in world. New level?");
auto& sprite = $level.world->get<components::Sprite>(item); auto& sprite = $level.world->get<components::Sprite>(item);
$gui.set_init<guecs::Sprite>(id, {fmt::format("{}_ICON", sprite.name)}); $gui.set_init<guecs::Icon>(id, {sprite.name});
guecs::GrabSource grabber{ guecs::GrabSource grabber{
item, [&, id]() { return remove_slot(id); }}; item, [&, id]() { return remove_slot(id); }};
@ -84,7 +84,7 @@ namespace gui {
} else { } else {
// BUG: fix remove so it's safe to call on empty // BUG: fix remove so it's safe to call on empty
if($gui.has<guecs::GrabSource>(id)) { if($gui.has<guecs::GrabSource>(id)) {
$gui.remove<guecs::Sprite>(id); $gui.remove<guecs::Icon>(id);
$gui.remove<guecs::GrabSource>(id); $gui.remove<guecs::GrabSource>(id);
} }

@ -49,15 +49,6 @@ namespace gui {
$gui.init(); $gui.init();
} }
void MapViewUI::save_map(int compass_dir) {
(void)compass_dir;
// confirm we get two different maps
auto out_img = $map_render->getTexture().copyToImage();
bool worked = out_img.saveToFile("tmp/map_render.png");
dbc::check(worked, "failed to render map");
}
void MapViewUI::render(sf::RenderWindow &window, int compass_dir) { void MapViewUI::render(sf::RenderWindow &window, int compass_dir) {
$gui.render(window); $gui.render(window);
System::draw_map($level, $map_tiles, $entity_map); System::draw_map($level, $map_tiles, $entity_map);

@ -24,6 +24,5 @@ namespace gui {
void update_level(GameLevel &level); void update_level(GameLevel &level);
void log(std::wstring msg); void log(std::wstring msg);
void update(); void update();
void save_map(int compass_dir);
}; };
} }

@ -44,7 +44,7 @@ namespace gui {
} }
void UI::START(Event) { void UI::START(Event) {
$ritual_ui = textures::get("ritual_crafting_area"); $ritual_ui = textures::get_sprite("ritual_crafting_area");
$ritual_ui.sprite->setPosition($gui.get_position()); $ritual_ui.sprite->setPosition($gui.get_position());
$ritual_ui.sprite->setTextureRect($ritual_closed_rect); $ritual_ui.sprite->setTextureRect($ritual_closed_rect);
$ritual_anim = animation::load("ritual_blanket"); $ritual_anim = animation::load("ritual_blanket");

@ -80,7 +80,7 @@ namespace gui {
auto gui_id = $gui.entity(slot); auto gui_id = $gui.entity(slot);
auto& sprite = $level.world->get<components::Sprite>(world_entity); auto& sprite = $level.world->get<components::Sprite>(world_entity);
$gui.set_init<guecs::Sprite>(gui_id, {fmt::format("{}_ICON", sprite.name)}); $gui.set_init<guecs::Icon>(gui_id, {sprite.name});
guecs::GrabSource grabber{ world_entity, guecs::GrabSource grabber{ world_entity,
[&, gui_id]() { return remove_slot(gui_id); }}; [&, gui_id]() { return remove_slot(gui_id); }};
grabber.setSprite($gui, gui_id); grabber.setSprite($gui, gui_id);
@ -136,7 +136,7 @@ namespace gui {
inventory.remove(world_entity); inventory.remove(world_entity);
$gui.remove<guecs::GrabSource>(slot_id); $gui.remove<guecs::GrabSource>(slot_id);
$gui.remove<guecs::Sprite>(slot_id); $gui.remove<guecs::Icon>(slot_id);
} }
void StatusUI::swap(guecs::Entity gui_a, guecs::Entity gui_b) { void StatusUI::swap(guecs::Entity gui_a, guecs::Entity gui_b) {

@ -423,7 +423,7 @@ void Raycaster::draw(sf::RenderTarget& target) {
} }
void Raycaster::update_sprite(DinkyECS::Entity ent, components::Sprite& sprite) { void Raycaster::update_sprite(DinkyECS::Entity ent, components::Sprite& sprite) {
auto sprite_txt = textures::get(sprite.name); auto sprite_txt = textures::get_sprite(sprite.name);
$sprites.insert_or_assign(ent, sprite_txt); $sprites.insert_or_assign(ent, sprite_txt);
} }

@ -42,7 +42,7 @@ TEST_CASE("animation utility API", "[animation]") {
textures::init(); textures::init();
animation::init(); animation::init();
auto blanket = textures::get("ritual_crafting_area"); auto blanket = textures::get_sprite("ritual_crafting_area");
auto anim = animation::load("ritual_blanket"); auto anim = animation::load("ritual_blanket");
anim.play(); anim.play();

@ -11,7 +11,7 @@ TEST_CASE("test texture management", "[textures]") {
components::init(); components::init();
textures::init(); textures::init();
auto spider = textures::get("hairy_spider"); auto spider = textures::get_sprite("hairy_spider");
REQUIRE(spider.sprite != nullptr); REQUIRE(spider.sprite != nullptr);
REQUIRE(spider.texture != nullptr); REQUIRE(spider.texture != nullptr);
REQUIRE(spider.frame_size.x == TEXTURE_WIDTH); REQUIRE(spider.frame_size.x == TEXTURE_WIDTH);

@ -7,33 +7,43 @@
#include <memory> #include <memory>
namespace textures { namespace textures {
using std::shared_ptr, std::make_shared; using std::shared_ptr, std::make_shared, nlohmann::json, std::string;
static TextureManager TMGR; static TextureManager TMGR;
static bool initialized = false; static bool initialized = false;
void load_sprites() { void load_sprite_textures(SpriteTextureMap &mapping, json &config, bool smooth) {
Config assets("assets/config.json"); for(auto& [name, settings] : config.items()) {
for(auto& [name, settings] : assets["sprites"].items()) {
auto texture = make_shared<sf::Texture>(settings["path"]); auto texture = make_shared<sf::Texture>(settings["path"]);
texture->setSmooth(assets["graphics"]["smooth_textures"]); texture->setSmooth(smooth);
auto sprite = make_shared<sf::Sprite>(*texture); auto sprite = make_shared<sf::Sprite>(*texture);
int width = settings["frame_width"]; int width = settings["frame_width"];
int height = settings["frame_height"]; int height = settings["frame_height"];
dbc::check(width % 2 == 0, dbc::check(width % 2 == 0,
fmt::format("sprite {} has invalid frame size", name)); fmt::format("sprite {} has invalid frame size {}", name, width));
sf::Vector2i frame_size{width, height}; sf::Vector2i frame_size{width, height};
sprite->setTextureRect({{0,0}, frame_size}); sprite->setTextureRect({{0,0}, frame_size});
TMGR.sprite_textures.try_emplace(name, sprite, texture, frame_size); dbc::check(!mapping.contains(name),
fmt::format("duplicate sprite/icon name {}", (string)name));
mapping.try_emplace(name, sprite, texture, frame_size);
} }
} }
void load_sprites() {
Config sprites("assets/config.json");
bool smooth = sprites["graphics"]["smooth_textures"];
load_sprite_textures(TMGR.sprite_textures, sprites["sprites"], smooth);
Config icons("assets/icons.json");
load_sprite_textures(TMGR.icon_textures, icons.json(), smooth);
}
inline void resize_shit(size_t size) { inline void resize_shit(size_t size) {
TMGR.surfaces.resize(size); TMGR.surfaces.resize(size);
TMGR.ceilings.resize(size); TMGR.ceilings.resize(size);
@ -49,12 +59,12 @@ namespace textures {
for(auto &el : tiles.items()) { for(auto &el : tiles.items()) {
auto &config = el.value(); auto &config = el.value();
const std::string& texture_fname = config["texture"]; const string& texture_fname = config["texture"];
size_t surface_i = config["id"]; size_t surface_i = config["id"];
dbc::check(!TMGR.name_to_id.contains(el.key()), dbc::check(!TMGR.name_to_id.contains(el.key()),
fmt::format("duplicate key in textures {}", fmt::format("duplicate key in textures {}",
(std::string)el.key())); (string)el.key()));
TMGR.name_to_id.insert_or_assign(el.key(), surface_i); TMGR.name_to_id.insert_or_assign(el.key(), surface_i);
@ -68,9 +78,9 @@ namespace textures {
// NOTE: ceilings defaults to 0 which is floor texture so only need to update // NOTE: ceilings defaults to 0 which is floor texture so only need to update
if(config.contains("ceiling")) { if(config.contains("ceiling")) {
const std::string& name = config["ceiling"]; const string& name = config["ceiling"];
dbc::check(tiles.contains(name), fmt::format("invalid ceiling name {} in tile config {}", name, (std::string)el.key())); dbc::check(tiles.contains(name), fmt::format("invalid ceiling name {} in tile config {}", name, (string)el.key()));
auto& ceiling = tiles[name]; auto& ceiling = tiles[name];
TMGR.ceilings[surface_i] = ceiling["id"]; TMGR.ceilings[surface_i] = ceiling["id"];
@ -80,7 +90,7 @@ namespace textures {
void load_map_tiles() { void load_map_tiles() {
Config config("./assets/map_tiles.json"); Config config("./assets/map_tiles.json");
nlohmann::json& tiles = config.json(); json& tiles = config.json();
for(auto tile : tiles) { for(auto tile : tiles) {
sf::Vector2i coords{tile["x"], tile["y"]}; sf::Vector2i coords{tile["x"], tile["y"]};
@ -107,12 +117,12 @@ namespace textures {
} }
} }
SpriteTexture get(const std::string& name) { SpriteTexture& get(const string& name, SpriteTextureMap& mapping) {
dbc::check(initialized, "you forgot to call textures::init()"); dbc::check(initialized, "you forgot to call textures::init()");
dbc::check(TMGR.sprite_textures.contains(name), dbc::check(mapping.contains(name),
fmt::format("!!!!! texture pack does not contain {} sprite", name)); fmt::format("!!!!! textures do not contain {} sprite", name));
auto result = TMGR.sprite_textures.at(name); auto& result = mapping.at(name);
dbc::check(result.sprite != nullptr, dbc::check(result.sprite != nullptr,
fmt::format("bad sprite from textures::get named {}", name)); fmt::format("bad sprite from textures::get named {}", name));
@ -122,7 +132,15 @@ namespace textures {
return result; return result;
} }
sf::Image load_image(const std::string& filename) { SpriteTexture get_sprite(const string& name) {
return get(name, TMGR.sprite_textures);
}
SpriteTexture get_icon(const string& name) {
return get(name, TMGR.icon_textures);
}
sf::Image load_image(const string& filename) {
sf::Image texture; sf::Image texture;
bool good = texture.loadFromFile(filename); bool good = texture.loadFromFile(filename);
dbc::check(good, fmt::format("failed to load {}", filename)); dbc::check(good, fmt::format("failed to load {}", filename));
@ -150,7 +168,7 @@ namespace textures {
return (const uint32_t *)TMGR.surfaces[ceiling_num].getPixelsPtr(); return (const uint32_t *)TMGR.surfaces[ceiling_num].getPixelsPtr();
} }
size_t get_id(const std::string& name) { size_t get_id(const string& name) {
dbc::check(TMGR.name_to_id.contains(name), dbc::check(TMGR.name_to_id.contains(name),
fmt::format("there is no texture named {} in tiles.json", name)); fmt::format("there is no texture named {} in tiles.json", name));
return TMGR.name_to_id.at(name); return TMGR.name_to_id.at(name);

@ -15,12 +15,15 @@ namespace textures {
sf::Vector2i frame_size; sf::Vector2i frame_size;
}; };
using SpriteTextureMap = std::unordered_map<std::string, SpriteTexture>;
struct TextureManager { struct TextureManager {
std::vector<sf::Image> surfaces; std::vector<sf::Image> surfaces;
std::vector<size_t> ceilings; std::vector<size_t> ceilings;
std::vector<wchar_t> map_tile_set; std::vector<wchar_t> map_tile_set;
std::vector<int> ambient_light; std::vector<int> ambient_light;
std::unordered_map<std::string, SpriteTexture> sprite_textures; SpriteTextureMap sprite_textures;
SpriteTextureMap icon_textures;
std::unordered_map<std::string, size_t> name_to_id; std::unordered_map<std::string, size_t> name_to_id;
std::unordered_map<wchar_t, sf::Sprite> map_sprites; std::unordered_map<wchar_t, sf::Sprite> map_sprites;
sf::Texture map_sprite_sheet{"./assets/map_tiles.png"}; sf::Texture map_sprite_sheet{"./assets/map_tiles.png"};
@ -28,7 +31,8 @@ namespace textures {
void init(); void init();
SpriteTexture get(const std::string& name); SpriteTexture get_sprite(const std::string& name);
SpriteTexture get_icon(const std::string& name);
sf::Image load_image(const std::string& filename); sf::Image load_image(const std::string& filename);

@ -78,7 +78,7 @@ int main(int argc, char *argv[]) {
window.setVerticalSyncEnabled(true); window.setVerticalSyncEnabled(true);
if(load_sprite) { if(load_sprite) {
sprite_texture = textures::get(sprite_name); sprite_texture = textures::get_sprite(sprite_name);
sprite_texture.sprite->setPosition({0,0}); sprite_texture.sprite->setPosition({0,0});
auto bounds = sprite_texture.sprite->getLocalBounds(); auto bounds = sprite_texture.sprite->getLocalBounds();
sf::Vector2f scale{u_resolution.x / bounds.size.x, sf::Vector2f scale{u_resolution.x / bounds.size.x,

Loading…
Cancel
Save