From 04350cb51e21b6919a05cb0d3d5fe7ccb7b25784 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Tue, 29 Oct 2024 18:33:11 -0400 Subject: [PATCH] GUI is now decoupled from the ECS using the new DinkyECS event queues. That makes it easier to update and change the GUI without having to constantly alter the systems. --- events.hpp | 5 +++++ gui.cpp | 45 ++++++++++++++++++++++++++++++++++++++++----- status.txt | 7 +++++++ systems.cpp | 17 ++++++----------- 4 files changed, 58 insertions(+), 16 deletions(-) create mode 100644 events.hpp diff --git a/events.hpp b/events.hpp new file mode 100644 index 0000000..b3bcecd --- /dev/null +++ b/events.hpp @@ -0,0 +1,5 @@ +#pragma once + +enum GUIEvent { + START, HIT, MISS, DEAD +}; diff --git a/gui.cpp b/gui.cpp index b471e32..055722b 100644 --- a/gui.cpp +++ b/gui.cpp @@ -23,6 +23,7 @@ #include "components.hpp" #include "systems.hpp" #include "collider.hpp" +#include "events.hpp" using std::string; using namespace fmt; @@ -109,12 +110,45 @@ void GUI::create_renderer() { bool GUI::handle_events() { sf::Event event; bool event_happened = false; + auto& log = $world.get_the(); + auto player = $world.get_the(); + auto sounds = $world.get_the(); + + while($world.has_event()) { + auto [evt, entity] = $world.recv(); + switch(evt) { + case GUIEvent::HIT: { + auto combat = $world.get(entity); + + if(entity == player.entity) { + log.log(format("Enemy HIT YOU, you have {} HP!", combat.hp)); + sounds.play("hit"); + shake(); + } else { + log.log(format("You HIT enemy, they have {} HP!", combat.hp)); + sounds.play("hit"); + shake(); + } + } break; + case GUIEvent::MISS: + if(entity == player.entity) { + log.log("You MISSED the enemy."); + } else { + log.log("Enemy MISSED YOU."); + } + break; + case GUIEvent::DEAD: + log.log("--- ENEMY DEAD!"); + break; + default: + log.log(format("INVALID EVENT! {},{}", evt, entity)); + } + } while($window.pollEvent(event)) { if(event.type == sf::Event::Closed) { $window.close(); } else if(event.type == sf::Event::KeyPressed) { - auto player = $world.get_the(); auto& player_motion = $world.get(player.entity); if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) { @@ -211,7 +245,7 @@ void GUI::draw_screen(bool clear, float map_off_x, float map_off_y) { continue; // skip these, just windows junk } else { // it's a visual cell - bg_sprite.setPosition({x, y}); + bg_sprite.setPosition({x+map_off_x, y+map_off_y}); sf::Sprite &sprite = get_text_sprite(tile); // should look into caching all this instead of calcing it each time @@ -222,7 +256,7 @@ void GUI::draw_screen(bool clear, float map_off_x, float map_off_y) { 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}); + sprite.setPosition({x+width_delta+map_off_x, y+height_delta+map_off_y}); // get the entity combat and make them light gray if dead if(tile == L'█') { @@ -259,8 +293,8 @@ void GUI::draw_screen(bool clear, float map_off_x, float map_off_y) { void GUI::shake() { for(int i = 0; i < 10; ++i) { - int x = Random::uniform(-10,10); - int y = Random::uniform(-10,10); + int x = Random::uniform(-20,20); + int y = Random::uniform(-20,20); // add x/y back to draw screen draw_screen(true, x, y); std::this_thread::sleep_for(1ms); @@ -271,6 +305,7 @@ void GUI::configure_world() { SoundManager sounds("./assets"); sounds.load("hit", "hit.wav"); $world.set_the(sounds); + $world.set_the(GUIEvent::START); dbc::check($game_map.room_count() > 1, "not enough rooms in map."); // configure a player as a fact of the world diff --git a/status.txt b/status.txt index 226048f..572334e 100644 --- a/status.txt +++ b/status.txt @@ -4,6 +4,13 @@ NOTES: * src/ftxui/screen/color.cpp * Just search for ugrep x1B * https://man7.org/linux/man-pages/man4/console_codes.4.html +* amit note: + +Struct A { + int data; + template A(T t) : data(static_cast(t)) {} +}; +A a(my_enum); TODO: diff --git a/systems.cpp b/systems.cpp index 157ebb2..b50efdc 100644 --- a/systems.cpp +++ b/systems.cpp @@ -4,7 +4,7 @@ #include #include "rand.hpp" #include "collider.hpp" -#include "sound.hpp" +#include "events.hpp" using std::string; using namespace fmt; @@ -84,13 +84,10 @@ void System::death(DinkyECS::World &world) { }); } - void System::combat(DinkyECS::World &world, Player &player) { auto& collider = world.get_the(); const auto& player_position = world.get(player.entity); auto& player_combat = world.get(player.entity); - auto& log = world.get_the(); - auto& sounds = world.get_the(); // this is guaranteed to not return the given position auto [found, nearby] = collider.neighbors(player_position.location); @@ -101,23 +98,21 @@ void System::combat(DinkyECS::World &world, Player &player) { int player_dmg = player_combat.attack(enemy_combat); if(player_dmg > 0) { - log.log(format("You HIT for {} damage, HP left {}.", player_dmg, enemy_combat.hp)); - sounds.play("hit"); + world.send(GUIEvent::HIT, entity); } else { - log.log("You missed! They're quick!"); + world.send(GUIEvent::MISS, entity); } if(enemy_combat.hp > 0) { int enemy_dmg = enemy_combat.attack(player_combat); if(enemy_dmg > 0) { - sounds.play("hit"); - log.log(format("Enemy HIT YOU for {} damage.", enemy_dmg)); + world.send(GUIEvent::HIT, player.entity); } else { - log.log("Enemy MISSED, you dodged it."); + world.send(GUIEvent::MISS, player.entity); } } else { - log.log("ENEMY DEAD! YOU WIN!"); + world.send(GUIEvent::DEAD, entity); } } }