Next phase of the refactor is done. Now to replace everything in Systems.

master
Zed A. Shaw 7 days ago
parent 644ff6edc0
commit 81e25f73bb
  1. 35
      autowalker.cpp
  2. 66
      game_level.cpp
  3. 27
      game_level.hpp
  4. 81
      gui/fsm.cpp
  5. 2
      gui/fsm.hpp
  6. 9
      levelmanager.cpp
  7. 2
      main.cpp
  8. 5
      meson.build
  9. 17
      systems.cpp
  10. 1
      systems.hpp

@ -1,14 +1,15 @@
#include "autowalker.hpp"
#include "ai_debug.hpp"
#include "gui/ritual_ui.hpp"
#include "game_level.hpp"
template<typename Comp>
int number_left(gui::FSM& fsm) {
int number_left() {
int count = 0;
fsm.$level.world->query<components::Position, Comp>(
Game::current_world()->query<components::Position, Comp>(
[&](const auto ent, auto&, auto&) {
if(ent != fsm.$level.player) {
if(ent != Game::current().player) {
count++;
}
});
@ -17,16 +18,16 @@ int number_left(gui::FSM& fsm) {
}
template<typename Comp>
Pathing compute_paths(gui::FSM& fsm) {
auto& walls_original = fsm.$level.map->$walls;
Pathing compute_paths() {
auto& walls_original = Game::current().map->$walls;
auto walls_copy = walls_original;
Pathing paths{matrix::width(walls_copy), matrix::height(walls_copy)};
fsm.$level.world->query<components::Position>(
Game::current().world->query<components::Position>(
[&](const auto ent, auto& position) {
if(ent != fsm.$level.player) {
if(fsm.$level.world->has<Comp>(ent)) {
if(ent != Game::current().player) {
if(Game::current().world->has<Comp>(ent)) {
paths.set_target(position.location);
} else {
// this will mark that spot as a wall so we don't path there temporarily
@ -53,11 +54,11 @@ void Autowalker::close_status() {
}
Pathing Autowalker::path_to_enemies() {
return compute_paths<components::Combat>(fsm);
return compute_paths<components::Combat>();
}
Pathing Autowalker::path_to_items() {
return compute_paths<components::InventoryItem>(fsm);
return compute_paths<components::InventoryItem>();
}
void Autowalker::handle_window_events() {
@ -88,8 +89,7 @@ void Autowalker::process_combat() {
}
Point Autowalker::get_current_position() {
auto& player_position = fsm.$level.world->get<components::Position>(fsm.$level.player);
return player_position.location;
return Game::player_position().location;
}
void Autowalker::path_fail(Matrix& bad_paths, Point pos) {
@ -110,7 +110,7 @@ bool Autowalker::path_player(Pathing& paths, Point& target_out) {
}
}
if(!fsm.$level.map->can_move(target_out)) {
if(!Game::current().map->can_move(target_out)) {
path_fail(paths.$paths, target_out);
return false;
}
@ -184,8 +184,8 @@ struct InventoryStats {
};
ai::State Autowalker::update_state(ai::State start) {
int enemy_count = number_left<components::Combat>(fsm);
int item_count = number_left<components::InventoryItem>(fsm);
int enemy_count = number_left<components::Combat>();
int item_count = number_left<components::InventoryItem>();
ai::set(start, "no_more_enemies", enemy_count == 0);
ai::set(start, "no_more_items", item_count == 0);
@ -330,7 +330,7 @@ void Autowalker::process_move(Pathing& paths) {
// what are we aiming at?
auto aimed_at = fsm.$main_ui.camera_aim();
if(aimed_at && fsm.$level.world->has<components::InventoryItem>(aimed_at)) {
if(aimed_at && Game::current_world()->has<components::InventoryItem>(aimed_at)) {
// NOTE: if we're aiming at an item then pick it up
// for now just loot it then close to get it off the map
send_event(gui::Event::LOOT_ITEM);
@ -349,7 +349,8 @@ void Autowalker::send_event(gui::Event ev) {
}
bool Autowalker::player_health_good() {
auto combat = fsm.$level.world->get<components::Combat>(fsm.$level.player);
auto world = Game::current_world();
auto combat = world->get<components::Combat>(Game::the_player());
return float(combat.hp) / float(combat.max_hp) > 0.5f;
}

@ -0,0 +1,66 @@
#include "game_level.hpp"
#include "levelmanager.hpp"
#include "components.hpp"
namespace Game {
using std::shared_ptr, std::string, std::make_shared;
shared_ptr<LevelManager> LEVELS;
bool initialized = false;
void init() {
LEVELS = make_shared<LevelManager>();
initialized = true;
}
LevelManager& get_the_manager() {
return *LEVELS;
}
shared_ptr<DinkyECS::World> current_world() {
return current().world;
}
shared_ptr<gui::BossFightUI> create_bossfight() {
return LEVELS->create_bossfight(current_world());
}
GameLevel& create_level() {
LEVELS->create_level(current_world());
return next();
}
GameLevel &next() {
return LEVELS->next();
}
GameLevel &previous() {
return LEVELS->previous();
}
GameLevel &current() {
return LEVELS->current();
}
size_t current_index() {
return LEVELS->current_index();
}
GameLevel &get(size_t index) {
return LEVELS->get(index);
}
DinkyECS::Entity spawn_enemy(const std::string& named) {
return LEVELS->spawn_enemy(named);
}
components::Position& player_position() {
auto world = current_world();
auto& player = world->get_the<components::Player>();
return world->get<components::Position>(player.entity);
}
DinkyECS::Entity the_player() {
return current().player;
}
}

@ -0,0 +1,27 @@
#pragma once
#include "dinkyecs.hpp"
#include "gui/boss_fight_ui.hpp"
struct GameLevel;
struct LevelManager;
namespace components {
struct Position;
}
namespace Game {
std::shared_ptr<gui::BossFightUI> create_bossfight();
GameLevel& create_level();
void init();
LevelManager& get_the_manager();
GameLevel &next();
GameLevel &previous();
GameLevel &current();
size_t current_index();
std::shared_ptr<DinkyECS::World> current_world();
GameLevel &get(size_t index);
DinkyECS::Entity spawn_enemy(const std::string& named);
components::Position& player_position();
DinkyECS::Entity the_player();
}

@ -12,19 +12,19 @@
#include "shaders.hpp"
#include <fmt/xchar.h>
#include "gui/guecstra.hpp"
#include "game_level.hpp"
namespace gui {
using namespace components;
FSM::FSM() :
$window(sf::VideoMode({SCREEN_WIDTH, SCREEN_HEIGHT}), "Zed's Raycaster Thing"),
$debug_ui($levels),
$debug_ui(Game::get_the_manager()),
$main_ui($window),
$level($levels.current()),
$combat_ui($level),
$status_ui($level),
$map_ui($level),
$loot_ui($level),
$combat_ui(Game::current()),
$status_ui(Game::current()),
$map_ui(Game::current()),
$loot_ui(Game::current()),
$font{FONT_FILE_NAME},
$dnd_loot($status_ui, $loot_ui, $window, $router)
{
@ -47,7 +47,8 @@ namespace gui {
}
void FSM::START(Event ) {
$main_ui.update_level($level);
auto& level = Game::current();
$main_ui.update_level(level);
$main_ui.init();
$loot_ui.init();
@ -58,7 +59,7 @@ namespace gui {
$combat_ui.init();
$status_ui.init();
$boss_fight_ui = $levels.create_bossfight($level.world);
$boss_fight_ui = Game::create_bossfight();
$boss_fight_ui->init();
$map_ui.init();
@ -72,7 +73,7 @@ namespace gui {
void FSM::MOVING(Event ) {
// this should be an optional that returns a point
if(auto move_to = $main_ui.play_move()) {
System::plan_motion($level, *move_to);
System::plan_motion(Game::current(), *move_to);
run_systems();
$main_ui.dirty();
state(State::IDLE);
@ -83,7 +84,7 @@ namespace gui {
using enum Event;
switch(ev) {
case TICK: {
System::combat($level, $temp_attack_id);
System::combat(Game::current(), $temp_attack_id);
run_systems();
state(State::IN_COMBAT);
} break;
@ -101,7 +102,7 @@ namespace gui {
void FSM::ROTATING(Event) {
if(auto aim = $main_ui.play_rotate()) {
auto& player_pos = System::player_position($level);
auto& player_pos = Game::player_position();
player_pos.aiming_at = *aim;
state(State::IDLE);
}
@ -109,7 +110,7 @@ namespace gui {
void FSM::COMBAT_ROTATE(Event) {
if(auto aim = $main_ui.play_rotate()) {
auto& player_pos = System::player_position($level);
auto& player_pos = Game::player_position();
player_pos.aiming_at = *aim;
state(State::IN_COMBAT);
}
@ -194,7 +195,7 @@ namespace gui {
auto gui_id = std::any_cast<guecs::Entity>(data);
auto& slot_name = $status_ui.$gui.name_for(gui_id);
if(System::use_item($level, slot_name)) {
if(System::use_item(Game::current(), slot_name)) {
$status_ui.update();
}
} break;
@ -206,7 +207,7 @@ namespace gui {
mouse_action({1 << guecs::ModBit::hover});
} break;
case AIM_CLICK:
System::pickup($level);
System::pickup(Game::current());
break;
default:
break; // ignore everything else
@ -272,11 +273,12 @@ namespace gui {
}
void FSM::try_move(int dir, bool strafe) {
auto& level = Game::current();
using enum State;
// prevent moving into occupied space
Point move_to = $main_ui.plan_move(dir, strafe);
if($level.map->can_move(move_to) && !$level.collision->occupied(move_to)) {
if(level.map->can_move(move_to) && !level.collision->occupied(move_to)) {
sound::play("walk");
state(MOVING);
} else {
@ -360,8 +362,9 @@ namespace gui {
event(Event::LOOT_OPEN);
break;
case KEY::Z: {
auto& player_pos = System::player_position($level);
System::distribute_loot($level, {player_pos.aiming_at});
auto& level = Game::current();
auto& player_pos = Game::player_position();
System::distribute_loot(level, {player_pos.aiming_at});
} break;
case KEY::X:
event(Event::STAIRS_DOWN);
@ -419,13 +422,14 @@ namespace gui {
}
void FSM::run_systems() {
System::generate_paths($level);
System::enemy_ai_initialize($level);
System::enemy_pathing($level);
System::collision($level);
System::motion($level);
System::lighting($level);
System::death($level);
auto& level = Game::current();
System::generate_paths(level);
System::enemy_ai_initialize(level);
System::enemy_pathing(level);
System::collision(level);
System::motion(level);
System::lighting(level);
System::death(level);
}
bool FSM::active() {
@ -434,11 +438,11 @@ namespace gui {
void FSM::handle_world_events() {
using eGUI = Events::GUI;
auto& world = *$level.world;
auto world = Game::current_world();
while(world.has_event<eGUI>()) {
auto [evt, entity, data] = world.recv<eGUI>();
auto player = world.get_the<Player>();
while(world->has_event<eGUI>()) {
auto [evt, entity, data] = world->recv<eGUI>();
auto player = world->get_the<Player>();
// HERE: this has to go, unify these events and just use them in the state machine directly
@ -463,7 +467,7 @@ namespace gui {
event(Event::START_COMBAT);
break;
case eGUI::ENTITY_SPAWN: {
auto& sprite = world.get<components::Sprite>(entity);
auto& sprite = world->get<components::Sprite>(entity);
$main_ui.$rayview->update_sprite(entity, sprite);
$main_ui.dirty();
run_systems();
@ -489,7 +493,7 @@ namespace gui {
event(Event::AIM_CLICK);
break;
case eGUI::LOOT_ITEM: {
dbc::check(world.has<components::InventoryItem>(entity),
dbc::check(world->has<components::InventoryItem>(entity),
"INVALID LOOT_ITEM, that entity has no InventoryItem");
$loot_ui.add_loose_item(entity);
event(Event::LOOT_ITEM);
@ -500,7 +504,7 @@ namespace gui {
event(Event::LOOT_OPEN);
} break;
case eGUI::HP_STATUS:
System::player_status($level);
System::player_status(Game::current());
break;
case eGUI::NEW_RITUAL:
$combat_ui.init();
@ -543,16 +547,15 @@ namespace gui {
}
void FSM::next_level() {
$levels.create_level($level.world);
$level = $levels.next();
auto& level = Game::create_level();
$status_ui.update_level($level);
$map_ui.update_level($level);
$combat_ui.update_level($level);
$main_ui.update_level($level);
$loot_ui.update_level($level);
$status_ui.update_level(level);
$map_ui.update_level(level);
$combat_ui.update_level(level);
$main_ui.update_level(level);
$loot_ui.update_level(level);
$boss_fight_ui = $levels.create_bossfight($level.world);
$boss_fight_ui = Game::create_bossfight();
$boss_fight_ui->init();
run_systems();

@ -35,10 +35,8 @@ namespace gui {
bool autowalking = false;
bool $map_open = false;
int $temp_attack_id = 0;
LevelManager $levels;
DebugUI $debug_ui;
MainUI $main_ui;
GameLevel $level;
shared_ptr<BossFightUI> $boss_fight_ui = nullptr;
CombatUI $combat_ui;
StatusUI $status_ui;

@ -27,16 +27,7 @@ inline shared_ptr<DinkyECS::World> clone_load_world(shared_ptr<DinkyECS::World>
auto world = make_shared<DinkyECS::World>();
if(prev_world != nullptr) {
fmt::println("############### NEW WORLD #################");
prev_world->clone_into(*world);
fmt::println("new world entity_count={}, prev={}", world->entity_count, prev_world->entity_count);
for(auto [ent, is_set] : prev_world->$constants) {
if(world->has<components::Sprite>(ent)) {
fmt::println("#### Sprite {} copied to new world.", ent);
}
}
} else {
save::load_configs(*world);
}

@ -7,6 +7,7 @@
#include <iostream>
#include "shaders.hpp"
#include "backend.hpp"
#include "game_level.hpp"
int main(int argc, char* argv[]) {
try {
@ -15,6 +16,7 @@ int main(int argc, char* argv[]) {
guecs::init(&backend);
ai::init("assets/ai.json");
animation::init();
Game::init();
if(DEBUG_BUILD) sound::mute(true);

@ -125,6 +125,7 @@ sources = [
'systems.cpp',
'textures.cpp',
'worldbuilder.cpp',
'game_level.cpp',
]
executable('runtests', sources + [
@ -160,10 +161,6 @@ executable('runtests', sources + [
override_options: exe_defaults,
dependencies: dependencies + [catch2])
executable('corostate',
['scratchpad/corostate.cpp'],
dependencies: [fmt])
executable('zedcaster',
sources + [ 'main.cpp' ],
cpp_args: cpp_args,

@ -16,6 +16,7 @@
#include <iostream>
#include "shaders.hpp"
#include "inventory.hpp"
#include "game_level.hpp"
using std::string;
using namespace fmt;
@ -55,7 +56,7 @@ void System::lighting(GameLevel &level) {
}
void System::generate_paths(GameLevel &level) {
const auto &player_pos = player_position(level);
const auto &player_pos = Game::player_position();
level.map->set_target(player_pos.location);
level.map->make_paths();
@ -91,7 +92,7 @@ void System::enemy_ai_initialize(GameLevel &level) {
void System::enemy_pathing(GameLevel &level) {
auto &world = *level.world;
auto &map = *level.map;
const auto &player_pos = player_position(level);
const auto &player_pos = Game::player_position();
world.query<Position, Motion>([&](auto ent, auto &position, auto &motion) {
if(ent != level.player) {
@ -228,7 +229,7 @@ void System::combat(GameLevel &level, int attack_id) {
if(!the_belt.has(attack_id)) return;
auto& ritual = the_belt.get(attack_id);
const auto& player_pos = player_position(level);
const auto& player_pos = Game::player_position();
auto& player_combat = world.get<Combat>(level.player);
// this is guaranteed to not return the given position
@ -279,7 +280,7 @@ void System::combat(GameLevel &level, int attack_id) {
void System::collision(GameLevel &level) {
auto &collider = *level.collision;
auto &world = *level.world;
const auto& player_pos = player_position(level);
const auto& player_pos = Game::player_position();
// this is guaranteed to not return the given position
auto [found, nearby] = collider.neighbors(player_pos.location);
@ -319,7 +320,7 @@ void System::remove_from_world(GameLevel &level, Entity entity) {
void System::pickup(GameLevel &level) {
auto &world = *level.world;
auto &collision = *level.collision;
auto pos = player_position(level);
auto pos = Game::player_position();
if(!collision.something_there(pos.aiming_at)) return;
@ -381,7 +382,7 @@ void System::device(World &world, Entity actor, Entity item) {
}
void System::plan_motion(GameLevel& level, Position move_to) {
auto& player_pos = player_position(level);
auto& player_pos = Game::player_position();
player_pos.aiming_at = move_to.aiming_at;
@ -479,10 +480,6 @@ void System::remove_from_container(World& world, Entity cont_id, const std::stri
container.remove(entity);
}
Position& System::player_position(GameLevel& level) {
auto& player = level.world->get_the<components::Player>();
return level.world->get<components::Position>(player.entity);
}
void System::inventory_swap(GameLevel &level, Entity container_id, const std::string& a_name, const std::string &b_name) {
dbc::check(a_name != b_name, "Attempt to inventory swap the same slot, you should check this and avoid calling me.");

@ -34,7 +34,6 @@ namespace System {
void remove_from_container(World& world, Entity cont_id, const std::string& name);
void remove_from_world(GameLevel &level, Entity entity);
Position& player_position(GameLevel& level);
void inventory_swap(GameLevel &level, Entity container_id, const std::string& a_name, const std::string &b_name);
bool inventory_occupied(GameLevel& level, Entity container_id, const std::string& name);

Loading…
Cancel
Save