A really shitty ritual crafting UI is working but needs a big reshape.

master
Zed A. Shaw 4 days ago
parent 14619558fa
commit 2ceab51c40
  1. 2
      Makefile
  2. 2
      assets/config.json
  3. 15
      assets/enemies.json
  4. BIN
      assets/gold_savior_oil-256.png
  5. 1
      debug_ui.cpp
  6. 11
      guecs.cpp
  7. 7
      guecs.hpp
  8. 1
      gui_fsm.cpp
  9. 76
      ritual_ui.cpp
  10. 2
      ritual_ui.hpp
  11. 30
      rituals.cpp
  12. 8
      rituals.hpp
  13. 32
      tests/rituals.cpp

@ -26,7 +26,7 @@ tracy_build:
meson compile -j 10 -C builddir meson compile -j 10 -C builddir
test: build test: build
./builddir/runtests "[rituals-belt]" ./builddir/runtests
run: build test run: build test
ifeq '$(OS)' 'Windows_NT' ifeq '$(OS)' 'Windows_NT'

@ -31,7 +31,7 @@
}, },
"sprites": { "sprites": {
"gold_savior": "gold_savior":
{"path": "assets/gold_savior-256.png", {"path": "assets/gold_savior_oil-256.png",
"frame_width": 256, "frame_width": 256,
"frame_height": 256 "frame_height": 256
}, },

@ -11,6 +11,21 @@
{"_type": "LightSource", "strength": 45, "radius": 2.0} {"_type": "LightSource", "strength": 45, "radius": 2.0}
] ]
}, },
"GOLD_SAVIOR": {
"components": [
{"_type": "Tile", "display": 2189,
"foreground": [131, 213, 238],
"background": [30, 20, 75]
},
{"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 1, "dead": false},
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
{"_type": "EnemyConfig", "ai_script": "Enemy::actions", "ai_start_name": "Enemy::initial_state", "ai_goal_name": "Enemy::final_state"},
{"_type": "Personality", "hearing_distance": 5, "tough": true},
{"_type": "Animation", "easing": 1, "ease_rate": 0.2, "scale": 0.1, "simple": true, "frames": 10, "speed": 0.3, "stationary": false},
{"_type": "Sprite", "name": "gold_savior", "width": 256, "height": 256, "width": 256, "height": 256, "scale": 1.0},
{"_type": "Sound", "attack": "Sword_Hit_2", "death": "Humanoid_Death_1"}
]
},
"KNIGHT": { "KNIGHT": {
"components": [ "components": [
{"_type": "Tile", "display": 2189, {"_type": "Tile", "display": 2189,

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

@ -29,6 +29,7 @@ namespace gui {
add_spawn_button("KNIGHT","armored_knight", "spawn2"); add_spawn_button("KNIGHT","armored_knight", "spawn2");
add_spawn_button("SPIDER_GIANT_HAIRY", "hairy_spider", "spawn3"); add_spawn_button("SPIDER_GIANT_HAIRY", "hairy_spider", "spawn3");
add_spawn_button("RAT_GIANT", "rat_with_sword", "spawn4"); add_spawn_button("RAT_GIANT", "rat_with_sword", "spawn4");
add_spawn_button("GOLD_SAVIOR", "gold_savior", "spawn5");
$gui.init(); $gui.init();
} }

@ -147,7 +147,7 @@ namespace guecs {
DinkyECS::Entity UI::entity(std::string name) { DinkyECS::Entity UI::entity(std::string name) {
dbc::check($name_ents.contains(name), dbc::check($name_ents.contains(name),
fmt::format("GUECS entity {} does not exist. Forgot to init_entity?", name)); fmt::format("GUECS entity {} does not exist. Mispelled cell name?", name));
return $name_ents.at(name); return $name_ents.at(name);
} }
@ -282,13 +282,8 @@ namespace guecs {
void UI::show_sprite(string region, string sprite_name) { void UI::show_sprite(string region, string sprite_name) {
auto ent = entity(region); auto ent = entity(region);
// BUG: this should have two branches that just update the sprite
if(!has<Sprite>(ent)) { set_init<Sprite>(ent, {sprite_name});
Sprite to_show{sprite_name};
auto& cell = cell_for(ent);
to_show.init(cell);
set<guecs::Sprite>(ent, to_show);
}
} }
void UI::show_text(string region, wstring content) { void UI::show_text(string region, wstring content) {

@ -203,10 +203,13 @@ namespace guecs {
$world.remove<Comp>(ent); $world.remove<Comp>(ent);
} }
// BUG: close could just be remove with overload
template <typename Comp> template <typename Comp>
void close(string region) { void close(string region) {
auto ent = entity(region); auto ent = entity(region);
remove<Comp>(ent); if(has<Comp>(ent)) {
remove<Comp>(ent);
}
} }
template<typename T> template<typename T>
@ -229,8 +232,6 @@ namespace guecs {
void show_sprite(string region, string sprite_name); void show_sprite(string region, string sprite_name);
void show_text(string region, wstring content); void show_text(string region, wstring content);
void update_text(string region, wstring content);
void update_label(string region, wstring content);
void show_label(string region, wstring content); void show_label(string region, wstring content);
}; };

@ -228,6 +228,7 @@ namespace gui {
void FSM::keyboard_mouse() { void FSM::keyboard_mouse() {
while(const auto ev = $window.pollEvent()) { while(const auto ev = $window.pollEvent()) {
if(ev->is<sf::Event::Closed>()) { if(ev->is<sf::Event::Closed>()) {
event(Event::QUIT); event(Event::QUIT);
} }

@ -24,8 +24,8 @@ namespace gui {
"[*%(100,200)result_image|_ |_]" "[*%(100,200)result_image|_ |_]"
"[_|_|_]" "[_|_|_]"
"[combine|_|_]" "[combine|_|_]"
"[_|craft1|craft2|craft3|craft4|_]" "[_|craft0|craft1|craft2|craft3|_]"
"[_|craft5|craft6|craft7|craft8|_]" "[_|craft4|craft5|craft6|craft7|_]"
"[ ritual_ui ]"); "[ ritual_ui ]");
} }
@ -49,10 +49,10 @@ namespace gui {
L"Celiac migas\nunicorn hexagon.\nBrooklyn williamsburg\ntruffaut pickled\nchillwave raclette\nchurch-key sus.", 16, ColorValue::LIGHT_LIGHT, 10}); L"Celiac migas\nunicorn hexagon.\nBrooklyn williamsburg\ntruffaut pickled\nchillwave raclette\nchurch-key sus.", 16, ColorValue::LIGHT_LIGHT, 10});
auto reset = $gui.entity("reset"); auto reset = $gui.entity("reset");
$gui.set<Rectangle>(reset, {}); $gui.set<Rectangle>(reset, {5, {60, 60, 60, 30}});
$gui.set<Label>(reset, L"reset"); $gui.set<Label>(reset, L"reset");
$gui.set<Clickable>(reset, { $gui.set<Clickable>(reset, {
[&](auto ent, auto){ reset_clicked(ent); } [&](auto, auto){ reset_inv_positions(); }
}); });
auto open_close_toggle = $gui.entity("ritual_ui"); auto open_close_toggle = $gui.entity("ritual_ui");
@ -73,45 +73,41 @@ namespace gui {
} }
void RitualUI::inv_slot_clicked(DinkyECS::Entity ent, DinkyECS::Entity item_id) { void RitualUI::inv_slot_clicked(DinkyECS::Entity ent, DinkyECS::Entity item_id) {
if($gui.has<Sprite>(ent)) { $selected.insert_or_assign(ent, item_id);
// auto& bs = $gui.get<Sprite>(ent);
// auto combine = $gui.entity("combine");
// do things to the combine button auto& blanket = $level.world->get_the<ritual::Blanket>();
blanket.select(item_id);
auto& blanket = $level.world->get_the<ritual::Blanket>();
auto& junk_item = blanket.get(item_id);
$engine.load_junk($craft_state, junk_item); update_items();
}
} }
void RitualUI::reset_inv_positions() { void RitualUI::reset_inv_positions() {
$craft_state.reset(); auto& blanket = $level.world->get_the<ritual::Blanket>();
auto combine = $gui.entity("combine"); blanket.reset();
$gui.world().query<lel::Cell, Sprite>( std::array<std::string, 8> temp_names{
[&](const auto ent, auto &cell, auto &bs) { "craft0","craft1","craft2","craft3",
if(ent == combine) { "craft4","craft5","craft6","craft7"
bs.sprite->setColor({255,255,255,255}); };
bs.sprite->setRotation(sf::degrees(0.0));
} else { for(const auto& name : temp_names) {
bs.sprite->setPosition({(float)cell.x, (float)cell.y}); $gui.close<Sprite>(name);
} }
});
}
void RitualUI::reset_clicked(DinkyECS::Entity ent) { update_items();
(void)ent; // make button animate
reset_inv_positions();
} }
void RitualUI::combine_clicked(DinkyECS::Entity ent) { void RitualUI::combine_clicked(DinkyECS::Entity ent) {
// auto cell = $gui.cell_for(ent); // auto cell = $gui.cell_for(ent);
auto& blanket = $level.world->get_the<ritual::Blanket>();
auto& bs = $gui.get<Sprite>(ent); auto& bs = $gui.get<Sprite>(ent);
bs.sprite->setColor({200, 0, 0}); bs.sprite->setColor({200, 0, 0});
// animation::center(*bs.sprite, {(float)cell.x, (float)cell.y});
animation::rotate(*bs.sprite, 20.0); $craft_state = $engine.start();
for(auto [ent, yes] : blanket.selected) {
$engine.load_junk($craft_state, blanket.get(ent));
}
// finalize here ritual here // finalize here ritual here
$engine.plan($craft_state); $engine.plan($craft_state);
@ -141,22 +137,26 @@ namespace gui {
void RitualUI::update_items() { void RitualUI::update_items() {
auto& blanket = $level.world->get_the<ritual::Blanket>(); auto& blanket = $level.world->get_the<ritual::Blanket>();
int i = 0; int i = 0;
int j = 0;
blanket.contents.query<ritual::JunkItem>([&](const auto item_id, auto& item) { for(auto& [item_id, item] : blanket.contents) {
auto button = $gui.entity("inv_slot", i++); auto button = $gui.entity("inv_slot", i++);
auto selector = $gui.entity("craft", j++);
std::string sprite_name = fmt::format("{}-64", item); std::string sprite_name = fmt::format("{}-64", item);
if($gui.has<Clickable>(button)) { if(blanket.is_selected(item_id)) {
$gui.set<Sprite>(button, {sprite_name}); $gui.set_init<Sprite>(selector, {sprite_name});
} else if($gui.has<Clickable>(button)) {
$gui.set_init<Sprite>(button, {sprite_name});
} else { } else {
$gui.set<Sprite>(button, {sprite_name}); $gui.set_init<Sprite>(button, {sprite_name});
$gui.set<Effect>(button, {0.4f}); $gui.set_init<Effect>(button, {0.4f});
$gui.set<Sound>(button, {"ui_click"}); $gui.set<Sound>(button, {"ui_click"});
$gui.set<Clickable>(button, { $gui.set<Clickable>(button, {
[&, item_id](auto ent, auto){ inv_slot_clicked(ent, item_id); } [&, item_id](auto ent, auto){ inv_slot_clicked(ent, item_id); }
}); });
} }
}); }
} }
void RitualUI::toggle() { void RitualUI::toggle() {
@ -166,7 +166,6 @@ namespace gui {
$ritual_state = CLOSING; $ritual_state = CLOSING;
} else if($ritual_state == CLOSED) { } else if($ritual_state == CLOSED) {
update_items(); update_items();
$gui.init();
$craft_state = $engine.start(); $craft_state = $engine.start();
$ritual_state = OPENING; $ritual_state = OPENING;
$ritual_anim.play(); $ritual_anim.play();
@ -191,6 +190,7 @@ namespace gui {
} }
window.draw(*$ritual_ui.sprite); window.draw(*$ritual_ui.sprite);
if($ritual_state == OPEN) { if($ritual_state == OPEN) {
$gui.render(window); $gui.render(window);
// $gui.debug_layout(window); // $gui.debug_layout(window);

@ -25,6 +25,7 @@ namespace gui {
components::Animation $ritual_anim; components::Animation $ritual_anim;
guecs::UI $gui; guecs::UI $gui;
GameLevel $level; GameLevel $level;
std::unordered_map<DinkyECS::Entity, DinkyECS::Entity> $selected;
RitualUI(GameLevel level); RitualUI(GameLevel level);
bool mouse(float x, float y, bool hover); bool mouse(float x, float y, bool hover);
@ -35,7 +36,6 @@ namespace gui {
void update(); void update();
void update_items(); void update_items();
void reset_clicked(DinkyECS::Entity ent);
void combine_clicked(DinkyECS::Entity ent); void combine_clicked(DinkyECS::Entity ent);
void inv_slot_clicked(DinkyECS::Entity ent, DinkyECS::Entity item_id); void inv_slot_clicked(DinkyECS::Entity ent, DinkyECS::Entity item_id);
void reset_inv_positions(); void reset_inv_positions();

@ -154,20 +154,38 @@ namespace ritual {
} }
DinkyECS::Entity Blanket::add(JunkItem name) { DinkyECS::Entity Blanket::add(JunkItem name) {
auto ent = contents.entity(); DinkyECS::Entity id = ++entity_counter;
contents.set(ent, name);
return ent; contents.insert_or_assign(id, name);
return id;
} }
std::string& Blanket::get(DinkyECS::Entity ent) { std::string& Blanket::get(DinkyECS::Entity ent) {
return contents.get<JunkItem>(ent); return contents.at(ent);
} }
bool Blanket::has(DinkyECS::Entity ent) { bool Blanket::has(DinkyECS::Entity ent) {
return contents.has<JunkItem>(ent); return contents.contains(ent);
} }
void Blanket::remove(DinkyECS::Entity ent) { void Blanket::remove(DinkyECS::Entity ent) {
contents.remove<JunkItem>(ent); contents.erase(ent);
}
void Blanket::select(DinkyECS::Entity ent) {
selected.insert_or_assign(ent, true);
}
void Blanket::deselect(DinkyECS::Entity ent) {
selected.erase(ent);
}
bool Blanket::is_selected(DinkyECS::Entity ent) {
return selected.contains(ent) && selected.at(ent);
}
void Blanket::reset() {
selected.clear();
} }
} }

@ -81,11 +81,17 @@ namespace ritual {
}; };
struct Blanket { struct Blanket {
DinkyECS::World contents; size_t entity_counter = 0;
std::unordered_map<DinkyECS::Entity, JunkItem> contents;
std::unordered_map<DinkyECS::Entity, bool> selected;
DinkyECS::Entity add(JunkItem name); DinkyECS::Entity add(JunkItem name);
JunkItem& get(DinkyECS::Entity ent); JunkItem& get(DinkyECS::Entity ent);
bool has(DinkyECS::Entity ent); bool has(DinkyECS::Entity ent);
void remove(DinkyECS::Entity ent); void remove(DinkyECS::Entity ent);
void select(DinkyECS::Entity ent);
void deselect(DinkyECS::Entity ent);
void reset();
bool is_selected(DinkyECS::Entity ent);
}; };
} }

@ -36,8 +36,9 @@ TEST_CASE("ritual::Engine basic tests", "[rituals]") {
re.set_state(craft_state, "has_magick", true); re.set_state(craft_state, "has_magick", true);
re.set_state(craft_state, "has_spikes", true); re.set_state(craft_state, "has_spikes", true);
re.set_state(craft_state, "shiny_bauble", true); re.set_state(craft_state, "shiny_bauble", true);
REQUIRE(craft_state.is_combined());
re.plan(craft_state); re.plan(craft_state);
REQUIRE(craft_state.is_combined());
fmt::println("\n\n------------ TEST WILL DO DAMAGE BOOST"); fmt::println("\n\n------------ TEST WILL DO DAMAGE BOOST");
craft_state.dump(); craft_state.dump();
@ -45,8 +46,9 @@ TEST_CASE("ritual::Engine basic tests", "[rituals]") {
re.set_state(craft_state, "has_magick", true); re.set_state(craft_state, "has_magick", true);
re.set_state(craft_state, "cursed_item", true); re.set_state(craft_state, "cursed_item", true);
re.set_state(craft_state, "shiny_bauble", true); re.set_state(craft_state, "shiny_bauble", true);
REQUIRE(craft_state.is_combined());
re.plan(craft_state); re.plan(craft_state);
REQUIRE(craft_state.is_combined());
fmt::println("\n\n------------ TEST WILL DO LARGE DAMAGE BOOST"); fmt::println("\n\n------------ TEST WILL DO LARGE DAMAGE BOOST");
craft_state.dump(); craft_state.dump();
} }
@ -69,7 +71,7 @@ TEST_CASE("craft_state can be finalized for the end result", "[rituals]") {
} }
TEST_CASE("the ritual belt works", "[rituals-belt]") { TEST_CASE("the ritual belt works", "[rituals]") {
ritual::Belt the_belt; ritual::Belt the_belt;
ritual::Engine re; ritual::Engine re;
auto craft_state = re.start(); auto craft_state = re.start();
@ -102,9 +104,10 @@ TEST_CASE("the ritual belt works", "[rituals-belt]") {
REQUIRE(!craft_state.is_combined()); REQUIRE(!craft_state.is_combined());
} }
TEST_CASE("ritual blanket basic operations", "[rituals]") { TEST_CASE("ritual blanket basic operations", "[rituals-blanket]") {
ritual::Blanket blanket; ritual::Blanket blanket;
DinkyECS::Entity other = blanket.add("rusty_nails");
DinkyECS::Entity ent = blanket.add("severed_finger"); DinkyECS::Entity ent = blanket.add("severed_finger");
auto& name = blanket.get(ent); auto& name = blanket.get(ent);
REQUIRE(name == "severed_finger"); REQUIRE(name == "severed_finger");
@ -112,4 +115,25 @@ TEST_CASE("ritual blanket basic operations", "[rituals]") {
REQUIRE(blanket.has(ent)); REQUIRE(blanket.has(ent));
blanket.remove(ent); blanket.remove(ent);
REQUIRE(!blanket.has(ent)); REQUIRE(!blanket.has(ent));
REQUIRE(blanket.has(other));
REQUIRE(!blanket.is_selected(ent));
REQUIRE(!blanket.is_selected(other));
blanket.select(ent);
REQUIRE(blanket.is_selected(ent));
REQUIRE(!blanket.is_selected(other));
blanket.deselect(ent);
REQUIRE(!blanket.is_selected(ent));
blanket.select(ent);
blanket.select(other);
REQUIRE(blanket.is_selected(ent));
REQUIRE(blanket.is_selected(other));
blanket.reset();
REQUIRE(!blanket.is_selected(ent));
REQUIRE(!blanket.is_selected(other));
REQUIRE(blanket.selected.empty());
REQUIRE(blanket.selected.size() == 0);
} }

Loading…
Cancel
Save