diff --git a/.gitmodules b/.gitmodules index e69de29..6474c8d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vendor/callable"] + path = vendor/callable + url = forgejo@git.objectionable.solutions:Sara/cpp-callable.git diff --git a/src/core/character.cpp b/src/core/character.cpp index e60c522..55e2277 100644 --- a/src/core/character.cpp +++ b/src/core/character.cpp @@ -1,39 +1,26 @@ #include "character.h" #include "core/renderer.h" #include "world.h" -#include -#include namespace rogue { -CharacterLogic::~CharacterLogic() {} - -void CharacterLogic::set_character(Character *character) { - this->character = character; -} - -Character::Character(Tile location, CharacterLogic *logic, CharacterData stats) +Character::Character(World &world, Tile location, CharacterData stats) : data{stats} -, logic{logic} , health{stats.health} , location{location} -, world{nullptr} { - this->logic->set_character(this); -} +, world{world} +{} void Character::act() { - assert(this->world != nullptr && "World generation did not initialize character properly"); if(this->health < 0) { return; } - this->logic->set_character(this); // get motion from logic - Tile target{this->logic->move()}; - if(target == this->location - || std::abs(target.x - this->location.x) + std::abs(target.y - this->location.y) != 1) { + Tile target{this->data.logic(*this)}; + if(target == this->location) { return; } // check resulting tile - TileData tile{world->query_tile(target)}; + TileData tile{world.query_tile(target)}; // if character, deal damage if(tile.character != nullptr) { tile.character->deal_damage(this->data.damage); @@ -51,8 +38,7 @@ void Character::draw() { bool Character::deal_damage(int damage) { return (this->health -= damage) <= 0; } - -Tile NullCharacterLogic::move() { - return this->character->location; +Tile null_character_logic_function(Character &character) { + return character.location; } } diff --git a/src/core/character.h b/src/core/character.h index ef3b955..6bfc618 100644 --- a/src/core/character.h +++ b/src/core/character.h @@ -2,46 +2,34 @@ #define ROGUE_CHARACTER_H #include "core/roguedefs.h" -#include namespace rogue { class World; class Character; -struct CharacterLogic { - virtual ~CharacterLogic(); - - virtual Tile move() = 0; -protected: - Character *character{nullptr}; -private: - friend class Character; - void set_character(Character *character); -}; +typedef Tile(&CharacterLogicFunction)(Character &character); struct CharacterData { int health{1}; int damage{1}; Sprite sprite{0}; + CharacterLogicFunction logic; }; struct Character { - Character(Tile location, CharacterLogic *logic, CharacterData stats); + Character(World &world, Tile location, CharacterData stats); void act(); void draw(); bool deal_damage(int damage); CharacterData const data; - std::shared_ptr logic{nullptr}; int health{1}; Tile location{0, 0}; - World *world{nullptr}; + World &world; }; -struct NullCharacterLogic : public CharacterLogic { - virtual Tile move() override; -}; +extern Tile null_character_logic_function(Character &character); } #endif // !ROGUE_CHARACTER_H diff --git a/src/core/input.cpp b/src/core/input.cpp deleted file mode 100644 index daa686d..0000000 --- a/src/core/input.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "input.h" -#include -#include -#include - -namespace rogue { -InputHandler::InputHandler() { - Input::add_handler(this); -} - -InputHandler::~InputHandler() { - Input::remove_handler(this); -} - -KeyEventHandler::KeyEventHandler(std::set code, Listener listener) -: scancode{code} -, listener{listener} {} - -void KeyEventHandler::process_event(SDL_Event event) { - if((event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) && this->scancode.contains(event.key.keysym.scancode)) { - this->listener(event.type == SDL_KEYDOWN); - } -} - -void Input::add_handler(InputHandler *handler) { - Input::handlers.insert(handler); -} - -void Input::remove_handler(InputHandler *handler) { - Input::handlers.erase(handler); -} - -void Input::process_event(SDL_Event event) { - for(InputHandler *handler : Input::handlers) { - handler->process_event(event); - } -} - -std::set Input::handlers{}; -} diff --git a/src/core/input.h b/src/core/input.h deleted file mode 100644 index 0d1a7ea..0000000 --- a/src/core/input.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef ROGUE_INPUT_H -#define ROGUE_INPUT_H - -#include -#include -#include -#include - -namespace rogue { -struct InputHandler { - InputHandler(); - virtual ~InputHandler(); - virtual void process_event(SDL_Event event) = 0; -}; - -struct KeyEventHandler : public InputHandler { - typedef std::function Listener; - KeyEventHandler(std::set code, Listener listener); - virtual void process_event(SDL_Event event) override; - std::set scancode{}; - Listener listener{}; -}; - -class Input { -public: - static void add_handler(InputHandler *handler); - static void remove_handler(InputHandler *handler); - static void process_event(SDL_Event event); -private: - static std::set handlers; -}; -} - -#endif // !ROGUE_INPUT_H diff --git a/src/core/world.cpp b/src/core/world.cpp index 6445d88..98b00ee 100644 --- a/src/core/world.cpp +++ b/src/core/world.cpp @@ -4,7 +4,6 @@ #include "core/roguedefs.h" #include #include -#include namespace rogue { void Room::draw(Tile world_pivot) { @@ -37,14 +36,6 @@ bool Room::tile_is_wall(Tile local_tile) const { return is_outside_room && is_outside_hallways; } -World::World() -: direction_pressed{{ - SDL_SCANCODE_H, SDL_SCANCODE_J, SDL_SCANCODE_K, SDL_SCANCODE_L, - SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_UP, SDL_SCANCODE_DOWN - }, - std::bind(&World::on_input, this, std::placeholders::_1) -} {} - void World::act() { for(Character &character : this->characters) { character.act(); @@ -52,7 +43,7 @@ void World::act() { } void World::render() { - Render::clear(this->player->location); + Render::clear({this->chunk_size/2, this->chunk_size/2}); for(size_t i{0}; i < this->rooms.size(); ++i) { this->rooms[i].draw({ .x = int(i % this->shear * this->chunk_size), @@ -83,12 +74,6 @@ TileData World::query_tile(Tile tile) { return out; } -void World::on_input(bool pressed) { - if(!pressed) { - this->act(); - } -} - WorldGenerator &WorldGenerator::with_chunk_size(unsigned side_length) { assert(this->chunk_side_length == 0); assert(side_length > 0); @@ -112,25 +97,22 @@ WorldGenerator &WorldGenerator::with_room_size(unsigned min_side_length, unsigne return *this; } -WorldGenerator &WorldGenerator::with_player(Character character) { - this->player.emplace(character); - return *this; -} - -std::unique_ptr WorldGenerator::generate() { +World WorldGenerator::generate() { assert(this->chunk_side_length > 0 && "Chunk size is required to generate world"); assert(this->min_room_size > 0 && "Room size is required to generate world"); assert(this->min_room_size < this->max_room_size && "Room size is required to generate world"); assert(this->world_side_length > 0 && "World size is required to generate world"); - assert(this->player.has_value() && "World cannot be generated without a player"); - std::unique_ptr world{new World()}; - world->characters.push_back(player.value()); - world->player = &world->characters[0]; - world->player->world = world.get(); - world->chunk_size = this->chunk_side_length; - world->shear = this->world_side_length; - world->rooms.reserve(this->world_side_length * this->world_side_length); - world->rooms.push_back(Room { + World world{}; + world.chunk_size = this->chunk_side_length; + world.shear = this->world_side_length; + world.characters.push_back(Character(world, {this->chunk_side_length/2, this->chunk_side_length/2}, CharacterData { + .health = 1, + .damage = 1, + .sprite = 0, + .logic = null_character_logic_function + })); + world.rooms.reserve(this->world_side_length * this->world_side_length); + world.rooms.push_back(Room { .hallway_paths = Directions(Directions::NORTH | Directions::EAST), .chunk_size = this->chunk_side_length, .rect = { diff --git a/src/core/world.h b/src/core/world.h index a9f38d5..e4f5809 100644 --- a/src/core/world.h +++ b/src/core/world.h @@ -1,11 +1,9 @@ #ifndef ROGUE_WORLD_H #define ROGUE_WORLD_H -#include #include #include #include "character.h" -#include "core/input.h" #include "core/roguedefs.h" namespace rogue { @@ -28,21 +26,18 @@ struct Room { struct World { friend class WorldGenerator; - World(); ~World() = default; void act(); void render(); Room &get_room(Chunk chunk); TileData query_tile(Tile tile); - void on_input(bool); private: int chunk_size{1}; unsigned shear{0}; - Character *player{nullptr}; std::vector rooms{}; std::vector characters{}; - KeyEventHandler direction_pressed; private: + World() = default; }; class WorldGenerator { @@ -51,10 +46,8 @@ public: WorldGenerator &with_chunk_size(unsigned side_length); WorldGenerator &with_world_size(unsigned side_length); WorldGenerator &with_room_size(unsigned min_side_length, unsigned max_side_length); - WorldGenerator &with_player(Character character); - std::unique_ptr generate(); + World generate(); private: - std::optional player; int chunk_side_length{0}, world_side_length{0}; int max_room_size{0}, min_room_size{0}; }; diff --git a/src/main.cpp b/src/main.cpp index dd5a620..f7497d1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,26 +1,14 @@ #include -#include -#include "core/character.h" -#include "core/input.h" #include "core/renderer.h" #include "core/world.h" -#include "player_logic.h" using namespace rogue; int main(int argc, char *argv[]) { - std::unique_ptr world{WorldGenerator() + World world{WorldGenerator() .with_world_size(5) .with_chunk_size(9) .with_room_size(2, 5) - .with_player(Character({9/2, 9/2}, - new PlayerCharacterLogic(), - CharacterData { - .health = 1, - .damage = 1, - .sprite = 0 - } - )) .generate() }; RenderData data{RenderDataSetup() @@ -34,13 +22,11 @@ int main(int argc, char *argv[]) { Render::provide_render_data(data); SDL_Event evt; for(;;) { - world->render(); + world.render(); Render::present(); if(SDL_WaitEvent(&evt)) { if(evt.type == SDL_QUIT) { goto main_loop; - } else { - Input::process_event(evt); } } } main_loop: diff --git a/src/player_logic.cpp b/src/player_logic.cpp deleted file mode 100644 index 4042f39..0000000 --- a/src/player_logic.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "player_logic.h" -#include - -namespace rogue { -PlayerCharacterLogic::PlayerCharacterLogic() -: up{{SDL_SCANCODE_K, SDL_SCANCODE_UP}, std::bind(&PlayerCharacterLogic::on_up, this, std::placeholders::_1)} -, down{{SDL_SCANCODE_J, SDL_SCANCODE_DOWN}, std::bind(&PlayerCharacterLogic::on_down, this, std::placeholders::_1)} -, right{{SDL_SCANCODE_L, SDL_SCANCODE_RIGHT}, std::bind(&PlayerCharacterLogic::on_right, this, std::placeholders::_1)} -, left{{SDL_SCANCODE_H, SDL_SCANCODE_LEFT}, std::bind(&PlayerCharacterLogic::on_left, this, std::placeholders::_1)} -{} - -Tile PlayerCharacterLogic::move() { - return { - this->character->location.x + input_x, - this->character->location.y + input_y - }; -} - -void PlayerCharacterLogic::on_up(bool pressed) { - if(pressed) { - input_x = 0; - input_y = -1; - } -} - -void PlayerCharacterLogic::on_down(bool pressed) { - if(pressed) { - input_x = 0; - input_y = 1; - } -} - -void PlayerCharacterLogic::on_left(bool pressed) { - if(pressed) { - input_x = -1; - input_y = 0; - } -} - -void PlayerCharacterLogic::on_right(bool pressed) { - if(pressed) { - input_x = 1; - input_y = 0; - } -} -}; diff --git a/src/player_logic.h b/src/player_logic.h deleted file mode 100644 index 6ddd106..0000000 --- a/src/player_logic.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef PLAYER_LOGIC_H -#define PLAYER_LOGIC_H - -#include "core/character.h" -#include "core/input.h" -#include "core/roguedefs.h" -#include - -namespace rogue { -class PlayerCharacterLogic : public CharacterLogic { -public: - PlayerCharacterLogic(); -private: - virtual Tile move() override; - void on_up(bool pressed); - void on_down(bool pressed); - void on_left(bool pressed); - void on_right(bool pressed); - int input_x{0}, input_y{0}; - KeyEventHandler up; - KeyEventHandler down; - KeyEventHandler right; - KeyEventHandler left; -}; -} - -#endif // !PLAYER_LOGIC_H diff --git a/vendor/callable b/vendor/callable new file mode 160000 index 0000000..ea96247 --- /dev/null +++ b/vendor/callable @@ -0,0 +1 @@ +Subproject commit ea96247ecb258ea9938f038f410e0fd2739aa5de