diff options
-rw-r--r-- | src/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/commands/insert_cell.cpp | 24 | ||||
-rw-r--r-- | src/commands/insert_cell.hpp | 20 | ||||
-rw-r--r-- | src/commands/move_cursor.cpp | 37 | ||||
-rw-r--r-- | src/commands/move_cursor.hpp | 27 | ||||
-rw-r--r-- | src/commands/quit.cpp | 8 | ||||
-rw-r--r-- | src/commands/quit.hpp | 9 | ||||
-rw-r--r-- | src/engine/engine.cpp | 37 | ||||
-rw-r--r-- | src/engine/engine.hpp | 6 | ||||
-rw-r--r-- | src/engine/user/input.cpp | 26 | ||||
-rw-r--r-- | src/engine/user/input.hpp | 13 | ||||
-rw-r--r-- | src/game/game.cpp | 20 | ||||
-rw-r--r-- | src/game/game.hpp | 11 | ||||
-rw-r--r-- | src/input_actions.cpp | 42 | ||||
-rw-r--r-- | src/input_actions.hpp | 22 | ||||
-rw-r--r-- | src/interfaces/command.hpp | 9 | ||||
-rw-r--r-- | src/interfaces/game.hpp | 11 | ||||
-rw-r--r-- | src/interfaces/input.hpp | 8 | ||||
-rw-r--r-- | src/interfaces/observable.hpp | 8 |
19 files changed, 223 insertions, 119 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3ad9b06..1a52ae8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,7 +13,6 @@ file(GLOB SOURCES bootstrap.cpp conversion.cpp argument_parser.cpp - input_actions.cpp util/color.cpp game/game.cpp engine/engine.cpp @@ -26,6 +25,9 @@ file(GLOB SOURCES engine/user/cursor.cpp randomization/generator.cpp randomization/seed_generator.cpp + commands/insert_cell.cpp + commands/move_cursor.cpp + commands/quit.cpp DI/object_type.cpp) add_executable(${PROJECT_NAME} ${SOURCES}) diff --git a/src/commands/insert_cell.cpp b/src/commands/insert_cell.cpp new file mode 100644 index 0000000..86a5a52 --- /dev/null +++ b/src/commands/insert_cell.cpp @@ -0,0 +1,24 @@ +#include "insert_cell.hpp" + +#include <iostream> + +InsertCellCommand::InsertCellCommand( + const std::shared_ptr<ICursorController> &cursor_controller, + const std::shared_ptr<IScene> &scene) noexcept + : _cursor_controller(cursor_controller), _scene(scene) +{ +} + +void InsertCellCommand::execute() noexcept +{ + const auto position = _cursor_controller->where(); + + std::cout.put('x'); + std::cout.flush(); + + _cursor_controller->move_to(position); + + auto matrix = _scene->get_matrix(); + + matrix->set(position - Vector2({.x = 0U, .y = 1U}), "#"); +} diff --git a/src/commands/insert_cell.hpp b/src/commands/insert_cell.hpp new file mode 100644 index 0000000..cf04203 --- /dev/null +++ b/src/commands/insert_cell.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "interfaces/command.hpp" +#include "interfaces/cursor.hpp" +#include "interfaces/scene.hpp" + +#include <memory> + +class InsertCellCommand : public ICommand +{ +public: + InsertCellCommand(const std::shared_ptr<ICursorController> &cursor_controller, + const std::shared_ptr<IScene> &scene) noexcept; + + void execute() noexcept override; + +private: + const std::shared_ptr<ICursorController> &_cursor_controller; + const std::shared_ptr<IScene> &_scene; +}; diff --git a/src/commands/move_cursor.cpp b/src/commands/move_cursor.cpp new file mode 100644 index 0000000..8dd7db7 --- /dev/null +++ b/src/commands/move_cursor.cpp @@ -0,0 +1,37 @@ +#include "move_cursor.hpp" + +#include "strings.hpp" + +#include <fmt/core.h> + +MoveCursorCommand::MoveCursorCommand( + const Vector2 &direction, const std::shared_ptr<ICursorController> &cursor_controller, + const std::shared_ptr<IScene> &scene, const std::shared_ptr<IWindow> &window) noexcept + : _direction(direction), + _cursor_controller(cursor_controller), + _scene(scene), + _window(window) + +{ +} + +void MoveCursorCommand::execute() noexcept +{ + constexpr int32_t amount = 1; + + const auto new_position = + _cursor_controller->where().to_direction(_direction, amount); + + const auto window_size = _window->size(); + + if (window_size.validate_coords(new_position) != CoordsValidation::VALID) + { + return; + } + + _cursor_controller->move_to(new_position); + + _scene->write_status(fmt::format(STATUS_BAR_COORDINATES, + fmt::arg("x", new_position.get_x()), + fmt::arg("y", new_position.get_y()))); +} diff --git a/src/commands/move_cursor.hpp b/src/commands/move_cursor.hpp new file mode 100644 index 0000000..14a87e0 --- /dev/null +++ b/src/commands/move_cursor.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "interfaces/command.hpp" +#include "interfaces/cursor.hpp" +#include "interfaces/scene.hpp" +#include "interfaces/window.hpp" + +#include "engine/data/vector2.hpp" + +#include <memory> + +class MoveCursorCommand : public ICommand +{ +public: + MoveCursorCommand(const Vector2 &direction, + const std::shared_ptr<ICursorController> &cursor_controller, + const std::shared_ptr<IScene> &scene, + const std::shared_ptr<IWindow> &window) noexcept; + + void execute() noexcept override; + +private: + Vector2 _direction; + const std::shared_ptr<ICursorController> &_cursor_controller; + const std::shared_ptr<IScene> &_scene; + const std::shared_ptr<IWindow> &_window; +}; diff --git a/src/commands/quit.cpp b/src/commands/quit.cpp new file mode 100644 index 0000000..c2a68e7 --- /dev/null +++ b/src/commands/quit.cpp @@ -0,0 +1,8 @@ +#include "quit.hpp" + +#include <cstdlib> + +void QuitCommand::execute() noexcept +{ + exit(EXIT_SUCCESS); +} diff --git a/src/commands/quit.hpp b/src/commands/quit.hpp new file mode 100644 index 0000000..cb1aefd --- /dev/null +++ b/src/commands/quit.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "interfaces/command.hpp" + +class QuitCommand : public ICommand +{ +public: + void execute() noexcept override; +}; diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index afa5924..b2add9c 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1,6 +1,5 @@ #include "engine.hpp" -#include "input_actions.hpp" #include "strings.hpp" #include "util/function.hpp" @@ -58,45 +57,23 @@ void CLIGameEngine::start() noexcept std::cout.flush(); })); - const std::unordered_map<char, Callback> input_config = { - {'q', InputActions::exit_success}, - {'i', - [this, scene]() - { - const auto position = _cursor_controller->where(); - - std::cout.put('x'); - std::cout.flush(); - - _cursor_controller->move_to(position); - - auto matrix = scene->get_matrix(); - - matrix->set(position - Vector2({.x = 0U, .y = 1U}), "#"); - }}, - {'k', - InputActions::move_cursor(Vector2::up(), _cursor_controller, scene, _window)}, - {'j', - InputActions::move_cursor(Vector2::down(), _cursor_controller, scene, _window)}, - {'h', - InputActions::move_cursor(Vector2::left(), _cursor_controller, scene, _window)}, - {'l', InputActions::move_cursor(Vector2::right(), _cursor_controller, scene, - _window)}}; + auto game = _game_factory(); - _configure_input(input_config); + _configure_input(game->get_input_config(_window, scene, _cursor_controller)); _input_handler->listen(); - auto game = _game_factory(); - game->run(); } void CLIGameEngine::_configure_input( - const std::unordered_map<char, Callback> &input_config) noexcept + const std::unordered_map<char, std::shared_ptr<ICommand>> &input_config) noexcept { for (const auto &config_pair : input_config) { - _input_handler->attach(config_pair.first, config_pair.second); + auto key = config_pair.first; + auto command = config_pair.second; + + _input_handler->attach(key, command); } } diff --git a/src/engine/engine.hpp b/src/engine/engine.hpp index 42cc297..32afa56 100644 --- a/src/engine/engine.hpp +++ b/src/engine/engine.hpp @@ -1,11 +1,11 @@ #pragma once #include "DI/auto_wirable.hpp" +#include "interfaces/command.hpp" #include "interfaces/cursor.hpp" #include "interfaces/engine.hpp" #include "interfaces/game.hpp" #include "interfaces/input.hpp" -#include "interfaces/observable.hpp" #include "interfaces/scene.hpp" #include "interfaces/window.hpp" @@ -33,6 +33,6 @@ private: std::shared_ptr<ICursorController> _cursor_controller; std::shared_ptr<IWindow> _window; - void - _configure_input(const std::unordered_map<char, Callback> &input_config) noexcept; + void _configure_input( + const std::unordered_map<char, std::shared_ptr<ICommand>> &input_config) noexcept; }; diff --git a/src/engine/user/input.cpp b/src/engine/user/input.cpp index 62aef67..f1685fd 100644 --- a/src/engine/user/input.cpp +++ b/src/engine/user/input.cpp @@ -12,26 +12,21 @@ void InputHandler::listen() const noexcept } } -void InputHandler::attach(const char &event, Callback callback) noexcept +void InputHandler::attach(const char &key, + const std::shared_ptr<ICommand> &command) noexcept { - if (_key_observers.count(event) == 0) - { - _key_observers[event] = std::vector<Callback>(); - } + auto key_index = _key_as_index(key); - _key_observers[event].push_back(callback); + _key_commands.at(key_index).push_back(command); } -void InputHandler::notify(const char &event) const noexcept +void InputHandler::notify(const char &key) const noexcept { - if (_key_observers.count(event) == 0) - { - return; - } + auto key_index = _key_as_index(key); - for (const auto &observer : _key_observers.at(event)) + for (const auto &command : _key_commands.at(key_index)) { - observer(); + command->execute(); } } @@ -62,3 +57,8 @@ void InputHandler::leave_raw_mode() noexcept _original_termios = nullptr; } + +InputHandler::_KeyCommandsSizeType InputHandler::_key_as_index(const char &key) noexcept +{ + return static_cast<_KeyCommandsSizeType>(static_cast<uint8_t>(key)); +} diff --git a/src/engine/user/input.hpp b/src/engine/user/input.hpp index 3dd7fa9..d2aa447 100644 --- a/src/engine/user/input.hpp +++ b/src/engine/user/input.hpp @@ -1,9 +1,11 @@ #pragma once #include "DI/auto_wirable.hpp" +#include "interfaces/command.hpp" #include "interfaces/input.hpp" #include "interfaces/observable.hpp" +#include <limits> #include <memory> #include <termios.h> #include <unordered_map> @@ -16,16 +18,21 @@ public: void listen() const noexcept override; - void attach(const char &event, Callback callback) noexcept override; + void attach(const char &key, + const std::shared_ptr<ICommand> &command) noexcept override; - void notify(const char &event) const noexcept override; + void notify(const char &key) const noexcept override; void enter_raw_mode() noexcept override; void leave_raw_mode() noexcept override; private: - std::unordered_map<char, std::vector<Callback>> _key_observers; + std::array<std::vector<std::shared_ptr<ICommand>>, CHAR_MAX> _key_commands; std::shared_ptr<termios> _original_termios = nullptr; + + using _KeyCommandsSizeType = decltype(_key_commands)::size_type; + + static _KeyCommandsSizeType _key_as_index(const char &key) noexcept; }; diff --git a/src/game/game.cpp b/src/game/game.cpp index d7e9056..45e6a79 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -1,3 +1,23 @@ #include "game.hpp" +#include "commands/insert_cell.hpp" +#include "commands/move_cursor.hpp" +#include "commands/quit.hpp" + void Game::run() noexcept {} + +std::unordered_map<char, std::shared_ptr<ICommand>> Game::get_input_config( + const std::shared_ptr<IWindow> &window, const std::shared_ptr<IScene> &scene, + const std::shared_ptr<ICursorController> &cursor_controller) const noexcept +{ + return {{'q', std::make_shared<QuitCommand>()}, + {'i', std::make_shared<InsertCellCommand>(cursor_controller, scene)}, + {'k', std::make_shared<MoveCursorCommand>(Vector2::up(), cursor_controller, + scene, window)}, + {'j', std::make_shared<MoveCursorCommand>(Vector2::down(), cursor_controller, + scene, window)}, + {'h', std::make_shared<MoveCursorCommand>(Vector2::left(), cursor_controller, + scene, window)}, + {'l', std::make_shared<MoveCursorCommand>(Vector2::right(), cursor_controller, + scene, window)}}; +} diff --git a/src/game/game.hpp b/src/game/game.hpp index 110b1c8..9ec5b41 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -1,7 +1,12 @@ #pragma once #include "DI/auto_wirable.hpp" +#include "interfaces/cursor.hpp" #include "interfaces/game.hpp" +#include "interfaces/scene.hpp" +#include "interfaces/window.hpp" + +#include <memory> class Game : public IGame, public AutoWirable<IGame, Game> { @@ -9,4 +14,10 @@ public: Game() noexcept = default; void run() noexcept override; + + [[nodiscard]] std::unordered_map<char, std::shared_ptr<ICommand>> + get_input_config(const std::shared_ptr<IWindow> &window, + const std::shared_ptr<IScene> &scene, + const std::shared_ptr<ICursorController> &cursor_controller) + const noexcept override; }; diff --git a/src/input_actions.cpp b/src/input_actions.cpp deleted file mode 100644 index fa41bdd..0000000 --- a/src/input_actions.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "input_actions.hpp" - -#include "strings.hpp" - -#include <fmt/core.h> - -namespace InputActions -{ - -void exit_success() noexcept -{ - exit(EXIT_SUCCESS); -} - -Callback move_cursor(const Vector2 &direction, - const std::shared_ptr<ICursorController> &cursor_controller, - const std::shared_ptr<IScene> &scene, - const std::shared_ptr<IWindow> &window) noexcept -{ - return [direction, cursor_controller, scene, window]() - { - constexpr int32_t amount = 1; - - const auto new_position = - cursor_controller->where().to_direction(direction, amount); - - const auto window_size = window->size(); - - if (window_size.validate_coords(new_position) != CoordsValidation::VALID) - { - return; - } - - cursor_controller->move_to(new_position); - - scene->write_status(fmt::format(STATUS_BAR_COORDINATES, - fmt::arg("x", new_position.get_x()), - fmt::arg("y", new_position.get_y()))); - }; -} - -} // namespace InputActions diff --git a/src/input_actions.hpp b/src/input_actions.hpp deleted file mode 100644 index b9c33c1..0000000 --- a/src/input_actions.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "interfaces/cursor.hpp" -#include "interfaces/observable.hpp" -#include "interfaces/scene.hpp" -#include "interfaces/window.hpp" - -#include "engine/data/vector2.hpp" - -#include <memory> - -namespace InputActions -{ - -void exit_success() noexcept; - -Callback move_cursor(const Vector2 &direction, - const std::shared_ptr<ICursorController> &cursor_controller, - const std::shared_ptr<IScene> &scene, - const std::shared_ptr<IWindow> &window) noexcept; - -} // namespace InputActions diff --git a/src/interfaces/command.hpp b/src/interfaces/command.hpp new file mode 100644 index 0000000..245bdd6 --- /dev/null +++ b/src/interfaces/command.hpp @@ -0,0 +1,9 @@ +#pragma once + +class ICommand +{ +public: + virtual ~ICommand() = default; + + virtual void execute() noexcept = 0; +}; diff --git a/src/interfaces/game.hpp b/src/interfaces/game.hpp index 3f9d735..cfff8c5 100644 --- a/src/interfaces/game.hpp +++ b/src/interfaces/game.hpp @@ -1,6 +1,12 @@ #pragma once +#include "interfaces/command.hpp" +#include "interfaces/cursor.hpp" +#include "interfaces/scene.hpp" +#include "interfaces/window.hpp" + #include <memory> +#include <unordered_map> class IGame { @@ -8,6 +14,11 @@ public: virtual ~IGame() = default; virtual void run() = 0; + + [[nodiscard]] virtual std::unordered_map<char, std::shared_ptr<ICommand>> + get_input_config( + const std::shared_ptr<IWindow> &window, const std::shared_ptr<IScene> &scene, + const std::shared_ptr<ICursorController> &cursor_controller) const noexcept = 0; }; using IGameFactory = std::shared_ptr<IGame> (*)(); diff --git a/src/interfaces/input.hpp b/src/interfaces/input.hpp index b243a16..82ad57c 100644 --- a/src/interfaces/input.hpp +++ b/src/interfaces/input.hpp @@ -1,7 +1,10 @@ #pragma once +#include "interfaces/command.hpp" #include "interfaces/observable.hpp" +#include <memory> + class IInputHandler : public IObservable<char> { public: @@ -9,9 +12,10 @@ public: void listen() const noexcept override = 0; - void attach(const char &event, Callback callback) noexcept override = 0; + void attach(const char &key, + const std::shared_ptr<ICommand> &command) noexcept override = 0; - void notify(const char &event) const noexcept override = 0; + void notify(const char &key) const noexcept override = 0; virtual void enter_raw_mode() noexcept = 0; diff --git a/src/interfaces/observable.hpp b/src/interfaces/observable.hpp index 1777b7d..21fed76 100644 --- a/src/interfaces/observable.hpp +++ b/src/interfaces/observable.hpp @@ -1,8 +1,9 @@ #pragma once -#include <functional> +#include "interfaces/command.hpp" -using Callback = std::function<void()>; +#include <functional> +#include <memory> template <typename Event> class IObservable @@ -12,7 +13,8 @@ public: virtual void listen() const noexcept = 0; - virtual void attach(const Event &event, Callback callback) noexcept = 0; + virtual void attach(const char &event, + const std::shared_ptr<ICommand> &command) noexcept = 0; virtual void notify(const Event &event) const noexcept = 0; }; |