Now have a mostly working inventory UI and can pickup items and see them. Next up, being able to use things by clicking on them.

master
Zed A. Shaw 10 months ago
parent fa6311f10c
commit b7f49aa719
  1. 1
      components.cpp
  2. 1
      components.hpp
  3. 13
      dinky_components.hpp
  4. 13
      guecs.hpp
  5. 5
      gui_fsm.cpp
  6. 4
      levelmanager.cpp
  7. 1
      levelmanager.hpp
  8. 67
      status_ui.cpp
  9. 7
      status_ui.hpp

@ -11,7 +11,6 @@ namespace components {
ENROLL_COMPONENT(Combat, hp, max_hp, damage, dead); ENROLL_COMPONENT(Combat, hp, max_hp, damage, dead);
ENROLL_COMPONENT(LightSource, strength, radius); ENROLL_COMPONENT(LightSource, strength, radius);
ENROLL_COMPONENT(Device, config, events); ENROLL_COMPONENT(Device, config, events);
ENROLL_COMPONENT(Sprite, name);
ENROLL_COMPONENT(Animation, scale, simple, frames, speed); ENROLL_COMPONENT(Animation, scale, simple, frames, speed);
ENROLL_COMPONENT(Sound, attack, death); ENROLL_COMPONENT(Sound, attack, death);

@ -108,4 +108,5 @@ namespace components {
// these need to be here if you're using components::convert outside of components.cpp // these need to be here if you're using components::convert outside of components.cpp
ENROLL_COMPONENT(Tile, display, foreground, background); ENROLL_COMPONENT(Tile, display, foreground, background);
ENROLL_COMPONENT(Sprite, name);
} }

@ -4,7 +4,6 @@
#include <nlohmann/json_fwd.hpp> #include <nlohmann/json_fwd.hpp>
#include "dinkyecs.hpp" #include "dinkyecs.hpp"
#define ENROLL_COMPONENT(COMPONENT, ...) \ #define ENROLL_COMPONENT(COMPONENT, ...) \
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(COMPONENT, __VA_ARGS__); \ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(COMPONENT, __VA_ARGS__); \
template <> struct NameOf<COMPONENT> { \ template <> struct NameOf<COMPONENT> { \
@ -25,6 +24,18 @@ namespace components {
return result; return result;
} }
template<typename COMPONENT> COMPONENT get(nlohmann::json &data) {
for (auto &i : data["components"]) {
if(i["_type"] == NameOf<COMPONENT>::name) {
COMPONENT result;
from_json(i, result);
return result;
}
}
return {};
}
template <typename COMPONENT> void enroll(ComponentMap &m) { template <typename COMPONENT> void enroll(ComponentMap &m) {
m[NameOf<COMPONENT>::name] = [](DinkyECS::World& world, DinkyECS::Entity ent, nlohmann::json &j) { m[NameOf<COMPONENT>::name] = [](DinkyECS::World& world, DinkyECS::Entity ent, nlohmann::json &j) {
COMPONENT c; COMPONENT c;

@ -9,6 +9,7 @@
#include <functional> #include <functional>
#include "events.hpp" #include "events.hpp"
#include "constants.hpp" #include "constants.hpp"
#include "components.hpp"
namespace guecs { namespace guecs {
using std::shared_ptr, std::make_shared; using std::shared_ptr, std::make_shared;
@ -154,6 +155,13 @@ namespace guecs {
$world.set<Comp>(ent, val); $world.set<Comp>(ent, val);
} }
template <typename Comp>
void set_init(DinkyECS::Entity ent, Comp val) {
auto& cell = get<lel::Cell>(ent);
val.init(cell);
$world.set<Comp>(ent, val);
}
lel::Cell& cell_for(DinkyECS::Entity entity) { lel::Cell& cell_for(DinkyECS::Entity entity) {
return $world.get<lel::Cell>(entity); return $world.get<lel::Cell>(entity);
} }
@ -168,6 +176,11 @@ namespace guecs {
return $world.get_if<Comp>(entity); return $world.get_if<Comp>(entity);
} }
template <typename Comp>
bool has(DinkyECS::Entity entity) {
return $world.has<Comp>(entity);
}
template <typename Comp> template <typename Comp>
void remove(DinkyECS::Entity ent) { void remove(DinkyECS::Entity ent) {
$world.remove<Comp>(ent); $world.remove<Comp>(ent);

@ -47,6 +47,7 @@ namespace gui {
$combat_ui.render(); $combat_ui.render();
$status_ui.render(); $status_ui.render();
$status_ui.log("Welcome to the game!"); $status_ui.log("Welcome to the game!");
$status_ui.update();
$renderer.init_terminal(); $renderer.init_terminal();
$map_ui.create_render(); $map_ui.create_render();
@ -342,21 +343,25 @@ namespace gui {
// $status_ui.log(fmt::format("You picked up a {}.", // $status_ui.log(fmt::format("You picked up a {}.",
// std::string(item.data["name"]))); // std::string(item.data["name"])));
$status_ui.log("You picked up an item."); $status_ui.log("You picked up an item.");
$status_ui.update();
} }
break; break;
case eGUI::ATTACK: case eGUI::ATTACK:
event(Event::ATTACK); event(Event::ATTACK);
break; break;
case eGUI::DEATH: { case eGUI::DEATH: {
$status_ui.update();
if(entity != player.entity) { if(entity != player.entity) {
$main_ui.dead_entity(entity); $main_ui.dead_entity(entity);
} }
} break; } break;
case eGUI::NOOP: case eGUI::NOOP:
$status_ui.log(fmt::format("NOOP EVENT! {},{}", evt, entity)); $status_ui.log(fmt::format("NOOP EVENT! {},{}", evt, entity));
$status_ui.update();
break; break;
default: default:
$status_ui.log(fmt::format("INVALID EVENT! {},{}", evt, entity)); $status_ui.log(fmt::format("INVALID EVENT! {},{}", evt, entity));
$status_ui.update();
} }
} }
} }

@ -42,7 +42,9 @@ size_t LevelManager::create_level(shared_ptr<DinkyECS::World> prev_world) {
// not sure if this is still needed // not sure if this is still needed
System::init_positions(*world, *collider); System::init_positions(*world, *collider);
$levels.emplace_back(index, map, world, auto player = world->get_the<Player>();
$levels.emplace_back(index, player.entity, map, world,
make_shared<LightRender>(map->width(), map->height()), make_shared<LightRender>(map->width(), map->height()),
collider); collider);

@ -12,6 +12,7 @@ using std::shared_ptr;
struct GameLevel { struct GameLevel {
size_t index; size_t index;
DinkyECS::Entity player;
shared_ptr<Map> map; shared_ptr<Map> map;
shared_ptr<DinkyECS::World> world; shared_ptr<DinkyECS::World> world;
shared_ptr<lighting::LightRender> lights; shared_ptr<lighting::LightRender> lights;

@ -1,5 +1,6 @@
#include "status_ui.hpp" #include "status_ui.hpp"
#include "components.hpp" #include "components.hpp"
#include "inventory.hpp"
#include "color.hpp" #include "color.hpp"
#include "guecs.hpp" #include "guecs.hpp"
#include "rand.hpp" #include "rand.hpp"
@ -12,35 +13,25 @@ namespace gui {
{ {
$gui.position(STATUS_UI_X, STATUS_UI_Y, STATUS_UI_WIDTH, STATUS_UI_HEIGHT); $gui.position(STATUS_UI_X, STATUS_UI_Y, STATUS_UI_WIDTH, STATUS_UI_HEIGHT);
$gui.layout( $gui.layout(
"[button1 | button2 | button3]" "[slot1 | slot2 | slot3]"
"[button4 | button5 | button6]" "[slot4 | slot5 | slot6]"
"[button7 | button8 | button9]" "[slot7 | slot8 | slot9]"
"[*%(100,300)log_view]" "[*%(100,300)log_view]"
"[_]" "[_]"
"[_]"); "[_]");
} }
void StatusUI::render() { void StatusUI::render() {
auto& world = $gui.world();
std::vector<std::string> fake_items{
"cinqueda", "healing_potion_small",
"torch_crappy", "barrel_small"};
for(auto& [name, cell] : $gui.cells()) { for(auto& [name, cell] : $gui.cells()) {
if(name == "log_view") { if(name == "log_view") {
$log_to = $gui.entity("log_view"); $log_to = $gui.entity("log_view");
world.set<Rectangle>($log_to, {}); $gui.set<Rectangle>($log_to, {});
world.set<Textual>($log_to, {"Welcome to the Game!", 20}); $gui.set<Textual>($log_to, {"Welcome to the Game!", 20});
} else { } else {
size_t selected_item = Random::uniform<size_t>(0, fake_items.size() - 1);
fmt::println("fake items {} but size {}", selected_item, fake_items.size());
auto& fake_item = fake_items[selected_item];
auto button = $gui.entity(name); auto button = $gui.entity(name);
world.set<Rectangle>(button, {}); $gui.set<Rectangle>(button, {});
world.set<Sprite>(button, {fake_item}); $gui.set<Textual>(button, {""});
world.set<Clickable>(button, $gui.set<Clickable>(button,
guecs::make_action(*$level.world, Events::GUI::NOOP)); guecs::make_action(*$level.world, Events::GUI::NOOP));
} }
} }
@ -48,14 +39,40 @@ namespace gui {
$gui.init(); $gui.init();
} }
void StatusUI::draw(sf::RenderWindow &window) { /* WARNING: This is really not the greatest way to do this. */
auto &world = $gui.world(); void StatusUI::update() {
auto &text = world.get<Textual>($log_to); if($gui.has<Textual>($log_to)) {
std::string log; auto& text = $gui.get<Textual>($log_to);
for(auto msg : $messages) { std::string log;
log += msg + "\n"; for(auto msg : $messages) {
log += msg + "\n";
}
text.update(log);
} }
text.update(log);
auto world = $level.world;
if(world->has<components::Inventory>($level.player)) {
auto& inventory = world->get<components::Inventory>($level.player);
if(inventory.count() > 0) {
size_t limit = std::min(inventory.count(), $slots.size());
for(size_t i = 0; i < limit; i++) {
auto slot = $gui.entity($slots[i]);
auto& item = inventory.get(i);
auto comp_sprite = components::get<components::Sprite>(item.data);
$gui.set_init<guecs::Sprite>(slot, {comp_sprite.name});
std::string count_label = item.count > 1 ? fmt::format("{}", item.count): "";
auto& label = $gui.get<Textual>(slot);
label.text->setString(count_label);
}
}
}
}
void StatusUI::draw(sf::RenderWindow &window) {
$gui.render(window); $gui.render(window);
} }

@ -10,6 +10,12 @@ namespace gui {
public: public:
guecs::UI $gui; guecs::UI $gui;
DinkyECS::Entity $log_to; DinkyECS::Entity $log_to;
std::array<std::string, 9> $slots = {
"slot1", "slot2", "slot3"
"slot4", "slot5", "slot6"
"slot7", "slot8", "slot9"
};
std::deque<std::string> $messages; std::deque<std::string> $messages;
GameLevel $level; GameLevel $level;
StatusUI(GameLevel level); StatusUI(GameLevel level);
@ -17,5 +23,6 @@ namespace gui {
void log(std::string msg); void log(std::string msg);
void render(); void render();
void draw(sf::RenderWindow &window); void draw(sf::RenderWindow &window);
void update();
}; };
} }