Event system now accepts any data and the GUI receives simpler events with data for them.
This commit is contained in:
parent
0e79288afc
commit
ed9d0de8e0
7 changed files with 45 additions and 57 deletions
|
@ -18,6 +18,7 @@ namespace DinkyECS {
|
|||
struct Event {
|
||||
int event = 0;
|
||||
Entity entity = 0;
|
||||
std::any data;
|
||||
};
|
||||
|
||||
typedef std::queue<Event> EventQueue;
|
||||
|
@ -105,9 +106,9 @@ namespace DinkyECS {
|
|||
}
|
||||
|
||||
template<typename Comp>
|
||||
void send(Comp event, Entity entity) {
|
||||
void send(Comp event, Entity entity, std::any data) {
|
||||
EventQueue &queue = queue_map_for<Comp>();
|
||||
queue.push({event, entity});
|
||||
queue.push({event, entity, data});
|
||||
}
|
||||
|
||||
template<typename Comp>
|
||||
|
@ -115,6 +116,7 @@ namespace DinkyECS {
|
|||
EventQueue &queue = queue_map_for<Comp>();
|
||||
Event evt = queue.front();
|
||||
queue.pop();
|
||||
// I could use tie here to auto extract the any
|
||||
return evt;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
namespace Events {
|
||||
enum GUI {
|
||||
START, HIT, MISS, DEAD, LOOT
|
||||
START, COMBAT, LOOT
|
||||
};
|
||||
|
||||
struct Combat {
|
||||
int player_did;
|
||||
int enemy_did;
|
||||
};
|
||||
}
|
||||
|
|
39
gui.cpp
39
gui.cpp
|
@ -104,31 +104,30 @@ void GUI::handle_world_events() {
|
|||
auto player = $world.get_the<Player>();
|
||||
|
||||
while($world.has_event<eGUI>()) {
|
||||
auto [evt, entity] = $world.recv<eGUI>();
|
||||
switch(evt) {
|
||||
case eGUI::HIT: {
|
||||
auto combat = $world.get<Combat>(entity);
|
||||
auto [evt, entity, data] = $world.recv<eGUI>();
|
||||
|
||||
if(entity == player.entity) {
|
||||
$log.log(format("Enemy HIT YOU, you have {} HP!", combat.hp));
|
||||
switch(evt) {
|
||||
case eGUI::COMBAT: {
|
||||
auto &damage = std::any_cast<Events::Combat&>(data);
|
||||
auto enemy_combat = $world.get<Combat>(entity);
|
||||
|
||||
if(damage.enemy_did > 0) {
|
||||
$log.log(format("Enemy HIT YOU for {} damage!", damage.enemy_did));
|
||||
$log.log(format("-- Enemy has {} HP left.", enemy_combat.hp));
|
||||
$sounds.play("hit");
|
||||
} else {
|
||||
$log.log(format("You HIT enemy, they have {} HP!", combat.hp));
|
||||
$sounds.play("hit");
|
||||
}
|
||||
} break;
|
||||
case eGUI::MISS:
|
||||
if(entity == player.entity) {
|
||||
$log.log("You MISSED the enemy.");
|
||||
} else {
|
||||
$log.log("Enemy MISSED YOU.");
|
||||
}
|
||||
break;
|
||||
case eGUI::DEAD:
|
||||
$log.log("--- ENEMY DEAD!");
|
||||
break;
|
||||
|
||||
if(damage.player_did > 0) {
|
||||
$log.log(format("You HIT enemy for {} damage!", damage.player_did));
|
||||
$sounds.play("hit");
|
||||
} else {
|
||||
$log.log("You MISSED the enemy.");
|
||||
}
|
||||
} break;
|
||||
case eGUI::LOOT: {
|
||||
auto loot = $world.get<Loot>(entity);
|
||||
auto &loot = std::any_cast<Loot&>(data);
|
||||
auto inventory = $world.get<Inventory>(player.entity);
|
||||
$log.log(format("You found {} gold. You have {} now.",
|
||||
loot.amount, inventory.gold));
|
||||
|
@ -182,7 +181,7 @@ void GUI::run_systems() {
|
|||
auto player = $world.get_the<Player>();
|
||||
System::enemy_pathing($world, $game_map, player);
|
||||
System::motion($world, $game_map);
|
||||
System::combat($world, player);
|
||||
System::collision($world, player);
|
||||
System::death($world);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,7 @@ NOTES:
|
|||
|
||||
|
||||
TODO:
|
||||
|
||||
* Event system could take additional data so that the events can be more coarse and simpler.
|
||||
* Simplify the combat/collision system so that it's not a bunch of if-cases.
|
||||
* Save file isn't saving gold.
|
||||
* Inventory needs to be better, but need some kinds of "weapons" or other loot to get and not just gold.
|
||||
* Run the ansi_parser on the whole UI so I can use colors and other glyphs.
|
||||
* Create a few more enemy types to fight.
|
||||
|
|
31
systems.cpp
31
systems.cpp
|
@ -91,7 +91,7 @@ void System::death(DinkyECS::World &world) {
|
|||
});
|
||||
}
|
||||
|
||||
void System::combat(DinkyECS::World &world, Player &player) {
|
||||
void System::collision(DinkyECS::World &world, Player &player) {
|
||||
auto& collider = world.get_the<spatial_map>();
|
||||
const auto& player_position = world.get<Position>(player.entity);
|
||||
auto& player_combat = world.get<Combat>(player.entity);
|
||||
|
@ -100,36 +100,23 @@ void System::combat(DinkyECS::World &world, Player &player) {
|
|||
auto [found, nearby] = collider.neighbors(player_position.location);
|
||||
|
||||
if(found) {
|
||||
// save some keystrokes
|
||||
using eGUI = Events::GUI;
|
||||
|
||||
for(auto entity : nearby) {
|
||||
if(world.has<Combat>(entity)) {
|
||||
auto& enemy_combat = world.get<Combat>(entity);
|
||||
int player_dmg = player_combat.attack(enemy_combat);
|
||||
|
||||
if(player_dmg > 0) {
|
||||
world.send<eGUI>(eGUI::HIT, entity);
|
||||
} else {
|
||||
world.send<eGUI>(eGUI::MISS, entity);
|
||||
}
|
||||
Events::Combat result {
|
||||
player_combat.attack(enemy_combat),
|
||||
enemy_combat.attack(player_combat)
|
||||
};
|
||||
|
||||
if(enemy_combat.hp > 0) {
|
||||
int enemy_dmg = enemy_combat.attack(player_combat);
|
||||
|
||||
if(enemy_dmg > 0) {
|
||||
world.send<eGUI>(eGUI::HIT, player.entity);
|
||||
} else {
|
||||
world.send<eGUI>(eGUI::MISS, player.entity);
|
||||
}
|
||||
} else {
|
||||
world.send<eGUI>(eGUI::DEAD, entity);
|
||||
}
|
||||
world.send<Events::GUI>(Events::GUI::COMBAT, entity, result);
|
||||
} else if(world.has<Loot>(entity)) {
|
||||
world.send<eGUI>(eGUI::LOOT, entity);
|
||||
auto &loot = world.get<Loot>(entity);
|
||||
auto loot = world.get<Loot>(entity);
|
||||
auto &loot_pos = world.get<Position>(entity);
|
||||
auto &inventory = world.get<Inventory>(player.entity);
|
||||
|
||||
world.send<Events::GUI>(Events::GUI::LOOT, entity, loot);
|
||||
inventory.gold += loot.amount;
|
||||
collider.remove(loot_pos.location);
|
||||
} else {
|
||||
|
|
|
@ -8,7 +8,7 @@ using namespace components;
|
|||
|
||||
namespace System {
|
||||
void motion(DinkyECS::World &world, Map &game_map);
|
||||
void combat(DinkyECS::World &world, Player &player);
|
||||
void collision(DinkyECS::World &world, Player &player);
|
||||
void death(DinkyECS::World &world);
|
||||
void enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player);
|
||||
void draw_map(DinkyECS::World &world, Map &game_map, ftxui::Canvas &canvas, size_t view_x, size_t view_y);
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
|
||||
using namespace fmt;
|
||||
using DinkyECS::Entity;
|
||||
using std::string;
|
||||
|
||||
struct Player {
|
||||
std::string name;
|
||||
string name;
|
||||
Entity eid;
|
||||
};
|
||||
|
||||
|
@ -129,22 +130,18 @@ enum GUIEvent {
|
|||
|
||||
TEST_CASE("confirm that the event system works", "[ecs]") {
|
||||
DinkyECS::World world;
|
||||
DinkyECS::Entity gui_ent = world.entity();
|
||||
DinkyECS::Entity player = world.entity();
|
||||
GUIEvent gui{GUIEvent::HIT};
|
||||
|
||||
world.set<GUIEvent>(gui_ent, gui);
|
||||
auto &gui_test = world.get<GUIEvent>(gui_ent);
|
||||
REQUIRE(gui == gui_test);
|
||||
|
||||
world.send<GUIEvent>(GUIEvent::HIT, player);
|
||||
world.send<GUIEvent>(GUIEvent::HIT, player, string{"hello"});
|
||||
|
||||
bool ready = world.has_event<GUIEvent>();
|
||||
REQUIRE(ready == true);
|
||||
|
||||
auto [event, entity] = world.recv<GUIEvent>();
|
||||
auto [event, entity, data] = world.recv<GUIEvent>();
|
||||
REQUIRE(event == GUIEvent::HIT);
|
||||
REQUIRE(entity == player);
|
||||
auto &str_data = std::any_cast<string&>(data);
|
||||
REQUIRE(string{"hello"} == str_data);
|
||||
|
||||
ready = world.has_event<GUIEvent>();
|
||||
REQUIRE(ready == false);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue