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.

main
Zed A. Shaw 3 weeks ago
parent da8011cb14
commit 04350cb51e
  1. 5
      events.hpp
  2. 45
      gui.cpp
  3. 7
      status.txt
  4. 17
      systems.cpp

@ -0,0 +1,5 @@
#pragma once
enum GUIEvent {
START, HIT, MISS, DEAD
};

@ -23,6 +23,7 @@
#include "components.hpp" #include "components.hpp"
#include "systems.hpp" #include "systems.hpp"
#include "collider.hpp" #include "collider.hpp"
#include "events.hpp"
using std::string; using std::string;
using namespace fmt; using namespace fmt;
@ -109,12 +110,45 @@ void GUI::create_renderer() {
bool GUI::handle_events() { bool GUI::handle_events() {
sf::Event event; sf::Event event;
bool event_happened = false; bool event_happened = false;
auto& log = $world.get_the<ActionLog>();
auto player = $world.get_the<Player>();
auto sounds = $world.get_the<SoundManager>();
while($world.has_event<GUIEvent>()) {
auto [evt, entity] = $world.recv<GUIEvent>();
switch(evt) {
case GUIEvent::HIT: {
auto combat = $world.get<Combat>(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)) { while($window.pollEvent(event)) {
if(event.type == sf::Event::Closed) { if(event.type == sf::Event::Closed) {
$window.close(); $window.close();
} else if(event.type == sf::Event::KeyPressed) { } else if(event.type == sf::Event::KeyPressed) {
auto player = $world.get_the<Player>();
auto& player_motion = $world.get<Motion>(player.entity); auto& player_motion = $world.get<Motion>(player.entity);
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) { 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 continue; // skip these, just windows junk
} else { } else {
// it's a visual cell // 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); sf::Sprite &sprite = get_text_sprite(tile);
// should look into caching all this instead of calcing it each time // 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; 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 // 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 // get the entity combat and make them light gray if dead
if(tile == L'') { if(tile == L'') {
@ -259,8 +293,8 @@ void GUI::draw_screen(bool clear, float map_off_x, float map_off_y) {
void GUI::shake() { void GUI::shake() {
for(int i = 0; i < 10; ++i) { for(int i = 0; i < 10; ++i) {
int x = Random::uniform<int>(-10,10); int x = Random::uniform<int>(-20,20);
int y = Random::uniform<int>(-10,10); int y = Random::uniform<int>(-20,20);
// add x/y back to draw screen // add x/y back to draw screen
draw_screen(true, x, y); draw_screen(true, x, y);
std::this_thread::sleep_for(1ms); std::this_thread::sleep_for(1ms);
@ -271,6 +305,7 @@ void GUI::configure_world() {
SoundManager sounds("./assets"); SoundManager sounds("./assets");
sounds.load("hit", "hit.wav"); sounds.load("hit", "hit.wav");
$world.set_the<SoundManager>(sounds); $world.set_the<SoundManager>(sounds);
$world.set_the<GUIEvent>(GUIEvent::START);
dbc::check($game_map.room_count() > 1, "not enough rooms in map."); dbc::check($game_map.room_count() > 1, "not enough rooms in map.");
// configure a player as a fact of the world // configure a player as a fact of the world

@ -4,6 +4,13 @@ NOTES:
* src/ftxui/screen/color.cpp * src/ftxui/screen/color.cpp
* Just search for ugrep x1B * Just search for ugrep x1B
* https://man7.org/linux/man-pages/man4/console_codes.4.html * https://man7.org/linux/man-pages/man4/console_codes.4.html
* amit note:
Struct A {
int data;
template <typename T> A(T t) : data(static_cast<int>(t)) {}
};
A a(my_enum);
TODO: TODO:

@ -4,7 +4,7 @@
#include <cmath> #include <cmath>
#include "rand.hpp" #include "rand.hpp"
#include "collider.hpp" #include "collider.hpp"
#include "sound.hpp" #include "events.hpp"
using std::string; using std::string;
using namespace fmt; using namespace fmt;
@ -84,13 +84,10 @@ void System::death(DinkyECS::World &world) {
}); });
} }
void System::combat(DinkyECS::World &world, Player &player) { void System::combat(DinkyECS::World &world, Player &player) {
auto& collider = world.get_the<spatial_map>(); auto& collider = world.get_the<spatial_map>();
const auto& player_position = world.get<Position>(player.entity); const auto& player_position = world.get<Position>(player.entity);
auto& player_combat = world.get<Combat>(player.entity); auto& player_combat = world.get<Combat>(player.entity);
auto& log = world.get_the<ActionLog>();
auto& sounds = world.get_the<SoundManager>();
// this is guaranteed to not return the given position // this is guaranteed to not return the given position
auto [found, nearby] = collider.neighbors(player_position.location); 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); int player_dmg = player_combat.attack(enemy_combat);
if(player_dmg > 0) { if(player_dmg > 0) {
log.log(format("You HIT for {} damage, HP left {}.", player_dmg, enemy_combat.hp)); world.send<GUIEvent>(GUIEvent::HIT, entity);
sounds.play("hit");
} else { } else {
log.log("You missed! They're quick!"); world.send<GUIEvent>(GUIEvent::MISS, entity);
} }
if(enemy_combat.hp > 0) { if(enemy_combat.hp > 0) {
int enemy_dmg = enemy_combat.attack(player_combat); int enemy_dmg = enemy_combat.attack(player_combat);
if(enemy_dmg > 0) { if(enemy_dmg > 0) {
sounds.play("hit"); world.send<GUIEvent>(GUIEvent::HIT, player.entity);
log.log(format("Enemy HIT YOU for {} damage.", enemy_dmg));
} else { } else {
log.log("Enemy MISSED, you dodged it."); world.send<GUIEvent>(GUIEvent::MISS, player.entity);
} }
} else { } else {
log.log("ENEMY DEAD! YOU WIN!"); world.send<GUIEvent>(GUIEvent::DEAD, entity);
} }
} }
} }

Loading…
Cancel
Save