diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/bootstrap.cpp | 6 | ||||
-rw-r--r-- | src/commands/insert_cell.cpp | 24 | ||||
-rw-r--r-- | src/commands/insert_cell.hpp | 21 | ||||
-rw-r--r-- | src/commands/move_cursor.cpp | 27 | ||||
-rw-r--r-- | src/commands/move_cursor.hpp | 25 | ||||
-rw-r--r-- | src/commands/quit.cpp | 8 | ||||
-rw-r--r-- | src/commands/quit.hpp | 9 | ||||
-rw-r--r-- | src/commands/toggle_pause.cpp | 21 | ||||
-rw-r--r-- | src/commands/toggle_pause.hpp | 21 | ||||
-rw-r--r-- | src/engine/engine.cpp | 24 | ||||
-rw-r--r-- | src/engine/engine.hpp | 11 | ||||
-rw-r--r-- | src/engine/graphics/scene.cpp | 34 | ||||
-rw-r--r-- | src/engine/graphics/scene.hpp | 6 | ||||
-rw-r--r-- | src/engine/user/input.cpp | 68 | ||||
-rw-r--r-- | src/engine/user/input.hpp | 37 | ||||
-rw-r--r-- | src/game/game.cpp | 98 | ||||
-rw-r--r-- | src/game/game.hpp | 8 | ||||
-rw-r--r-- | src/game/status_manager.cpp | 1 | ||||
-rw-r--r-- | src/interfaces/game.hpp | 8 | ||||
-rw-r--r-- | src/interfaces/input.hpp | 20 | ||||
-rw-r--r-- | src/interfaces/statusline.hpp | 3 |
22 files changed, 167 insertions, 317 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6fd044f..0b40358 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,10 +27,6 @@ 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 - commands/toggle_pause.cpp DI/container.cpp DI/object_type.cpp) diff --git a/src/bootstrap.cpp b/src/bootstrap.cpp index 14aa922..6d42263 100644 --- a/src/bootstrap.cpp +++ b/src/bootstrap.cpp @@ -44,7 +44,7 @@ auto bootstrap() noexcept -> yacppdic::Container auto container = yacppdic::Container(); container.bind<IArgumentParser>().to<ArgumentParser>(); - container.bind<IInputHandler>().to<InputHandler>(); + container.bind<IUserInputObserver>().to<UserInputObserver>(); container.bind<ICursorController>().to<CursorController>(); container.bind<ICLIGameEngine>().to<CLIGameEngine>(); container.bind<ISeedGenerator>().to<SeedGenerator>(); @@ -52,7 +52,8 @@ auto bootstrap() noexcept -> yacppdic::Container container.bind<IGameFactory>().to_factory( [&container]( const std::shared_ptr<IScene> &scene, - const std::shared_ptr<ICursorController> &cursor_controller) + const std::shared_ptr<ICursorController> &cursor_controller, + const std::shared_ptr<IUserInputObserver> user_input_observer) { std::shared_ptr<IStatusLine> statusline = container.get<IStatusLineFactory>()(cursor_controller, scene); @@ -71,6 +72,7 @@ auto bootstrap() noexcept -> yacppdic::Container cursor_controller, generation_tracker, status_manager, + user_input_observer, vector2_statusline_subscriber_adapter_factory); }); diff --git a/src/commands/insert_cell.cpp b/src/commands/insert_cell.cpp deleted file mode 100644 index 86a5a52..0000000 --- a/src/commands/insert_cell.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#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 deleted file mode 100644 index 9d54736..0000000 --- a/src/commands/insert_cell.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#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 deleted file mode 100644 index 6bd8eda..0000000 --- a/src/commands/move_cursor.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "move_cursor.hpp" - -MoveCursorCommand::MoveCursorCommand( - const Vector2 &direction, - const std::shared_ptr<ICursorController> &cursor_controller, - const std::shared_ptr<IScene> &scene) noexcept - : _direction(direction), _cursor_controller(cursor_controller), _scene(scene) - -{ -} - -void MoveCursorCommand::execute() noexcept -{ - constexpr int32_t amount = 1; - - const auto new_position = - _cursor_controller->where().to_direction(_direction, amount); - - const auto scene_size = _scene->size(); - - if (scene_size.validate_coords(new_position) != CoordsValidation::VALID) - { - return; - } - - _cursor_controller->move_to(new_position); -} diff --git a/src/commands/move_cursor.hpp b/src/commands/move_cursor.hpp deleted file mode 100644 index dc08c64..0000000 --- a/src/commands/move_cursor.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "interfaces/command.hpp" -#include "interfaces/cursor.hpp" -#include "interfaces/scene.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) noexcept; - - void execute() noexcept override; - -private: - Vector2 _direction; - const std::shared_ptr<ICursorController> &_cursor_controller; - const std::shared_ptr<IScene> &_scene; -}; diff --git a/src/commands/quit.cpp b/src/commands/quit.cpp deleted file mode 100644 index c2a68e7..0000000 --- a/src/commands/quit.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "quit.hpp" - -#include <cstdlib> - -void QuitCommand::execute() noexcept -{ - exit(EXIT_SUCCESS); -} diff --git a/src/commands/quit.hpp b/src/commands/quit.hpp deleted file mode 100644 index cb1aefd..0000000 --- a/src/commands/quit.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "interfaces/command.hpp" - -class QuitCommand : public ICommand -{ -public: - void execute() noexcept override; -}; diff --git a/src/commands/toggle_pause.cpp b/src/commands/toggle_pause.cpp deleted file mode 100644 index 852e093..0000000 --- a/src/commands/toggle_pause.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "toggle_pause.hpp" - -#include <fmt/core.h> -#include <utility> - -TogglePauseCommand::TogglePauseCommand( - std::shared_ptr<IGenerationTracker> generation_tracker, - std::shared_ptr<IStatusManager> status_manager) noexcept - : _generation_tracker(std::move(generation_tracker)), - _status_manager(std::move(status_manager)) -{ -} - -void TogglePauseCommand::execute() noexcept -{ - auto onoff = !_generation_tracker->get_is_paused(); - - _generation_tracker->set_is_paused(onoff); - - _status_manager->set_section_body(StatusLineSection::D, onoff ? "yes" : "no"); -} diff --git a/src/commands/toggle_pause.hpp b/src/commands/toggle_pause.hpp deleted file mode 100644 index 41427cc..0000000 --- a/src/commands/toggle_pause.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "interfaces/command.hpp" -#include "interfaces/generation_tracker.hpp" -#include "interfaces/status_manager.hpp" - -#include <memory> - -class TogglePauseCommand : public ICommand -{ -public: - explicit TogglePauseCommand( - std::shared_ptr<IGenerationTracker> generation_tracker, - std::shared_ptr<IStatusManager> status_manager) noexcept; - - void execute() noexcept override; - -private: - std::shared_ptr<IGenerationTracker> _generation_tracker; - std::shared_ptr<IStatusManager> _status_manager; -}; diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 774220a..c7605b5 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -9,11 +9,11 @@ CLIGameEngine::CLIGameEngine( IGameFactory game_factory, ISceneFactory scene_factory, - std::shared_ptr<IInputHandler> input_handler, + std::shared_ptr<IUserInputObserver> user_input_observer, std::shared_ptr<ICursorController> cursor_controller) noexcept : _game_factory(std::move(game_factory)), _scene_factory(std::move(scene_factory)), - _input_handler(std::move(input_handler)), + _user_input_observer(std::move(user_input_observer)), _cursor_controller(std::move(cursor_controller)) { } @@ -23,9 +23,8 @@ void CLIGameEngine::start() noexcept std::shared_ptr<IScene> scene = _scene_factory(_cursor_controller); scene->enter(); - _input_handler->enter_raw_mode(); - auto game = _game_factory(scene, _cursor_controller); + auto game = _game_factory(scene, _cursor_controller, _user_input_observer); game->on_start(); @@ -33,17 +32,14 @@ void CLIGameEngine::start() noexcept [this, scene, &game]() { scene->leave(); - _input_handler->leave_raw_mode(); game->on_exit(); })); - _configure_input(game->get_input_config()); - auto listen_input_thread = std::thread(normalize_lambda( [this]() { - _input_handler->listen(); + _user_input_observer->listen(); })); auto last_update_time = std::chrono::system_clock::now(); @@ -68,17 +64,7 @@ void CLIGameEngine::start() noexcept game->on_update(); last_update_time = std::chrono::system_clock::now(); - } -} - -void CLIGameEngine::_configure_input( - const std::unordered_map<char, std::shared_ptr<ICommand>> &input_config) noexcept -{ - for (const auto &config_pair : input_config) - { - auto key = config_pair.first; - auto command = config_pair.second; - _input_handler->subscribe(key, command); + _user_input_observer->clear_currently_pressed(); } } diff --git a/src/engine/engine.hpp b/src/engine/engine.hpp index 1e8a217..b34ea2b 100644 --- a/src/engine/engine.hpp +++ b/src/engine/engine.hpp @@ -12,7 +12,7 @@ #include <memory> #include <unordered_map> -constexpr auto MIN_TIME_SINCE_LAST_UPDATE_MILLIS = 100; +constexpr auto MIN_TIME_SINCE_LAST_UPDATE_MILLIS = 40; class CLIGameEngine : public ICLIGameEngine, public yacppdic::AutoWirable< @@ -20,14 +20,14 @@ class CLIGameEngine : public ICLIGameEngine, CLIGameEngine, IGameFactory, ISceneFactory, - IInputHandler, + IUserInputObserver, ICursorController> { public: CLIGameEngine( IGameFactory game_factory, ISceneFactory scene_factory, - std::shared_ptr<IInputHandler> input_handler, + std::shared_ptr<IUserInputObserver> user_input_observer, std::shared_ptr<ICursorController> cursor_controller) noexcept; void start() noexcept override; @@ -36,9 +36,6 @@ private: IGameFactory _game_factory; ISceneFactory _scene_factory; - std::shared_ptr<IInputHandler> _input_handler; + std::shared_ptr<IUserInputObserver> _user_input_observer; std::shared_ptr<ICursorController> _cursor_controller; - - void _configure_input( - const std::unordered_map<char, std::shared_ptr<ICommand>> &input_config) noexcept; }; diff --git a/src/engine/graphics/scene.cpp b/src/engine/graphics/scene.cpp index 52613d8..b0d77b8 100644 --- a/src/engine/graphics/scene.cpp +++ b/src/engine/graphics/scene.cpp @@ -13,36 +13,60 @@ Scene::Scene( IMatrixFactory<std::string_view> matrix_factory, std::shared_ptr<ICursorController> cursor_controller) noexcept - : _is_shown(false), - _matrix(matrix_factory(size() - Bounds({.width = 0U, .height = 1U}))), - _cursor_controller(std::move(cursor_controller)) + : _matrix(matrix_factory(size() - Bounds({.width = 0U, .height = 1U}))), + _cursor_controller(std::move(cursor_controller)), + _is_shown(false) { _matrix->fill(" "); } void Scene::enter() noexcept { - if (_is_shown) + if (_is_shown || _original_termios != nullptr) { return; } + // Enable alternative buffer fmt::print(ENABLE_ALT_BUFFER, fmt::arg("esc", ESC)); std::cout.flush(); + // Create a backup of the current terminal state + _original_termios = std::make_shared<termios>(); + tcgetattr(STDIN_FILENO, _original_termios.get()); + + auto new_termios = termios(*_original_termios); + + // Set the local mode flags of the new termios structure + // + // The following flags are disabled: + // ECHO - Echoing input characters + // ICANON - Canonical mode (line by line input) + // ISIG - Generate the corresponding signals for the characters + // INTR, QUIT, SUSP and DSUSP + new_termios.c_lflag &= static_cast<uint32_t>(~(ECHO | ICANON | ISIG)); + + // Set a new terminal state + tcsetattr(STDIN_FILENO, TCSAFLUSH, &new_termios); + _is_shown = true; } void Scene::leave() noexcept { - if (!_is_shown) + if (!_is_shown || _original_termios == nullptr) { return; } + // Disable alternative buffer fmt::print(DISABLE_ALT_BUFFER, fmt::arg("esc", ESC)); std::cout.flush(); + // Restore the original terminal state + tcsetattr(STDIN_FILENO, TCSAFLUSH, _original_termios.get()); + + _original_termios = nullptr; _is_shown = false; } diff --git a/src/engine/graphics/scene.hpp b/src/engine/graphics/scene.hpp index 268f8dc..e57e1f8 100644 --- a/src/engine/graphics/scene.hpp +++ b/src/engine/graphics/scene.hpp @@ -8,6 +8,7 @@ #include <memory> #include <string_view> +#include <termios.h> constexpr fmt::string_view ENABLE_ALT_BUFFER = "{esc}[?1049h"; constexpr fmt::string_view DISABLE_ALT_BUFFER = "{esc}[?1049l"; @@ -29,8 +30,9 @@ public: -> const std::shared_ptr<IMatrix<std::string_view>> & override; private: - bool _is_shown; - std::shared_ptr<IMatrix<std::string_view>> _matrix; std::shared_ptr<ICursorController> _cursor_controller; + + bool _is_shown; + std::shared_ptr<termios> _original_termios = nullptr; }; diff --git a/src/engine/user/input.cpp b/src/engine/user/input.cpp index 7e9fe22..ac6d660 100644 --- a/src/engine/user/input.cpp +++ b/src/engine/user/input.cpp @@ -3,66 +3,46 @@ #include <iostream> #include <unistd.h> -void InputHandler::listen() const noexcept -{ - char character = 0; +#include <iostream> - while (!std::cin.read(&character, 1).fail()) +void UserInputObserver::listen() noexcept +{ + while (true) { - notify_subscribers(character, nullptr); - } -} + char character = 0; -void InputHandler::subscribe( - const Event &event, - const std::shared_ptr<ISubscriber<Context>> &subscriber) noexcept -{ - auto event_index = _event_as_index(event); + if (std::cin.read(&character, 1).fail()) + { + continue; + } - _subscribers.at(event_index).push_back(subscriber); -} + _currently_pressed_mutex.lock(); -void InputHandler::notify_subscribers(const Event &event, const Context &context) - const noexcept -{ - auto event_index = _event_as_index(event); + if (character != _currently_pressed) + { + _currently_pressed = character; + } - for (const auto &subscriber : _subscribers.at(event_index)) - { - subscriber->update(context); + _currently_pressed_mutex.unlock(); } } -void InputHandler::enter_raw_mode() noexcept +bool UserInputObserver::is_key_pressed(Key key) noexcept { - if (_original_termios == nullptr) - { - _original_termios = std::make_shared<termios>(); - } + _currently_pressed_mutex.lock(); - tcgetattr(STDIN_FILENO, _original_termios.get()); + const auto is_key_pressed = key == _currently_pressed; - auto raw_termios = termios(*_original_termios); + _currently_pressed_mutex.unlock(); - raw_termios.c_lflag &= static_cast<uint32_t>(~(ECHO | ICANON | ISIG)); - - tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw_termios); + return is_key_pressed; } -void InputHandler::leave_raw_mode() noexcept +void UserInputObserver::clear_currently_pressed() noexcept { - if (_original_termios == nullptr) - { - return; - } - - tcsetattr(STDIN_FILENO, TCSAFLUSH, _original_termios.get()); + _currently_pressed_mutex.lock(); - _original_termios = nullptr; -} + _currently_pressed = 0; -auto InputHandler::_event_as_index(const Event &event) noexcept - -> InputHandler::SubscribersSizeType -{ - return static_cast<SubscribersSizeType>(static_cast<uint8_t>(event)); + _currently_pressed_mutex.unlock(); } diff --git a/src/engine/user/input.hpp b/src/engine/user/input.hpp index f17472b..2fb97ac 100644 --- a/src/engine/user/input.hpp +++ b/src/engine/user/input.hpp @@ -5,40 +5,23 @@ #include <yacppdic/auto_wirable.hpp> -#include <array> -#include <climits> #include <memory> -#include <termios.h> -#include <vector> +#include <mutex> -class InputHandler : public IInputHandler, - public yacppdic::AutoWirable<IInputHandler, InputHandler> +class UserInputObserver + : public IUserInputObserver, + public yacppdic::AutoWirable<IUserInputObserver, UserInputObserver> { public: - InputHandler() noexcept = default; + UserInputObserver() noexcept = default; - void listen() const noexcept override; + void listen() noexcept override; - void subscribe( - const Event &event, - const std::shared_ptr<ISubscriber<Context>> &subscriber) noexcept override; + bool is_key_pressed(Key key) noexcept override; - void notify_subscribers(const Event &event, const Context &context) - const noexcept override; - - void enter_raw_mode() noexcept override; - - void leave_raw_mode() noexcept override; + void clear_currently_pressed() noexcept override; private: - std::array< - std::vector<std::shared_ptr<ISubscriber<Context>>>, - static_cast<std::size_t>(CHAR_MAX * 2U)> - _subscribers; - - std::shared_ptr<termios> _original_termios = nullptr; - - using SubscribersSizeType = decltype(_subscribers)::size_type; - - static auto _event_as_index(const Event &event) noexcept -> SubscribersSizeType; + Key _currently_pressed; + std::mutex _currently_pressed_mutex; }; diff --git a/src/game/game.cpp b/src/game/game.cpp index b9f5e3a..5606e71 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -1,13 +1,9 @@ #include "game.hpp" -#include "commands/insert_cell.hpp" -#include "commands/move_cursor.hpp" -#include "commands/quit.hpp" -#include "commands/toggle_pause.hpp" - #include <fmt/core.h> #include <chrono> +#include <cstdlib> #include <iostream> #include <utility> @@ -16,12 +12,14 @@ Game::Game( std::shared_ptr<ICursorController> cursor_controller, std::shared_ptr<IGenerationTracker> generation_tracker, std::shared_ptr<IStatusManager> status_manager, + std::shared_ptr<IUserInputObserver> user_input_observer, IStatusLineSubscriberAdapterFactory<Vector2> vector2_statusline_subscriber_adapter_factory) noexcept : _scene(std::move(scene)), _cursor_controller(std::move(cursor_controller)), _generation_tracker(std::move(generation_tracker)), _status_manager(std::move(status_manager)), + _user_input_observer(std::move(user_input_observer)), _vector2_statusline_subscriber_adapter_factory( vector2_statusline_subscriber_adapter_factory) { @@ -71,11 +69,63 @@ void Game::on_start() noexcept _status_manager->set_section_body(StatusLineSection::F, "0"); + _status_manager->set_section_body(StatusLineSection::G, "lol"); + _last_update_time = std::chrono::system_clock::now(); } void Game::on_update() noexcept { + if (_user_input_observer->is_key_pressed('q')) + { + std::exit(EXIT_SUCCESS); + } + + if (_user_input_observer->is_key_pressed('i')) + { + const auto position = _cursor_controller->where(); + + std::cout.put('x'); + std::cout.flush(); + + _cursor_controller->move_to(position); + + auto matrix = _scene->get_matrix(); + + const auto pos_offset = Vector2({.x = 0U, .y = 1U}); + + matrix->set(position - pos_offset, "#"); + } + + if (_user_input_observer->is_key_pressed('h')) + { + _move_cursor(Vector2::left()); + } + + if (_user_input_observer->is_key_pressed('j')) + { + _move_cursor(Vector2::down()); + } + + if (_user_input_observer->is_key_pressed('k')) + { + _move_cursor(Vector2::up()); + } + + if (_user_input_observer->is_key_pressed('l')) + { + _move_cursor(Vector2::right()); + } + + if (_user_input_observer->is_key_pressed('p')) + { + auto onoff = !_generation_tracker->get_is_paused(); + + _generation_tracker->set_is_paused(onoff); + + _status_manager->set_section_body(StatusLineSection::D, onoff ? "yes" : "no"); + } + const auto time_since_last_update = std::chrono::system_clock::now() - _last_update_time; @@ -84,6 +134,10 @@ void Game::on_update() noexcept fmt::format("{} nanoseconds", time_since_last_update.count())); _last_update_time = std::chrono::system_clock::now(); + + _status_manager->set_section_body( + StatusLineSection::G, + fmt::format("{}", _user_input_observer->is_key_pressed('v'))); } void Game::on_exit() const noexcept @@ -101,28 +155,16 @@ void Game::on_exit() const noexcept std::cout.flush(); } -auto Game::get_input_config() const noexcept - -> std::unordered_map<char, std::shared_ptr<ICommand>> +void Game::_move_cursor(const Vector2 &direction) noexcept { - return { - {'q', std::make_shared<QuitCommand>()}, - {'i', std::make_shared<InsertCellCommand>(_cursor_controller, _scene)}, - {'p', std::make_shared<TogglePauseCommand>(_generation_tracker, _status_manager)}, - {'k', - std::make_shared<MoveCursorCommand>(Vector2::up(), _cursor_controller, _scene)}, - {'j', - std::make_shared<MoveCursorCommand>( - Vector2::down(), - _cursor_controller, - _scene)}, - {'h', - std::make_shared<MoveCursorCommand>( - Vector2::left(), - _cursor_controller, - _scene)}, - {'l', - std::make_shared<MoveCursorCommand>( - Vector2::right(), - _cursor_controller, - _scene)}}; + const auto new_position = _cursor_controller->where().to_direction(direction, 1); + + const auto scene_size = _scene->size(); + + if (scene_size.validate_coords(new_position) != CoordsValidation::VALID) + { + return; + } + + _cursor_controller->move_to(new_position); } diff --git a/src/game/game.hpp b/src/game/game.hpp index fb2ad63..fb6a5ed 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -3,6 +3,7 @@ #include "interfaces/cursor.hpp" #include "interfaces/game.hpp" #include "interfaces/generation_tracker.hpp" +#include "interfaces/input.hpp" #include "interfaces/scene.hpp" #include "interfaces/status_manager.hpp" #include "interfaces/statusline_subscriber_adapter.hpp" @@ -18,6 +19,7 @@ public: std::shared_ptr<ICursorController> cursor_controller, std::shared_ptr<IGenerationTracker> generation_tracker, std::shared_ptr<IStatusManager> status_manager, + std::shared_ptr<IUserInputObserver> user_input_observer, IStatusLineSubscriberAdapterFactory<Vector2> vector2_statusline_subscriber_adapter_factory) noexcept; @@ -27,16 +29,16 @@ public: void on_exit() const noexcept override; - [[nodiscard]] auto get_input_config() const noexcept - -> std::unordered_map<char, std::shared_ptr<ICommand>> override; - private: std::shared_ptr<IScene> _scene; std::shared_ptr<ICursorController> _cursor_controller; std::shared_ptr<IGenerationTracker> _generation_tracker; std::shared_ptr<IStatusManager> _status_manager; + std::shared_ptr<IUserInputObserver> _user_input_observer; IStatusLineSubscriberAdapterFactory<Vector2> _vector2_statusline_subscriber_adapter_factory; std::chrono::system_clock::time_point _last_update_time; + + void _move_cursor(const Vector2 &direction) noexcept; }; diff --git a/src/game/status_manager.cpp b/src/game/status_manager.cpp index 33174d1..9bd4f37 100644 --- a/src/game/status_manager.cpp +++ b/src/game/status_manager.cpp @@ -18,6 +18,7 @@ void StatusManager::initialize() noexcept _statusline->set_section_length(StatusLineSection::D, 20U); _statusline->set_section_length(StatusLineSection::E, 25U); _statusline->set_section_length(StatusLineSection::F, 50U); + _statusline->set_section_length(StatusLineSection::G, 25U); _statusline->initialize_background(); } diff --git a/src/interfaces/game.hpp b/src/interfaces/game.hpp index a54782a..3aac6a9 100644 --- a/src/interfaces/game.hpp +++ b/src/interfaces/game.hpp @@ -2,12 +2,12 @@ #include "interfaces/command.hpp" #include "interfaces/cursor.hpp" +#include "interfaces/input.hpp" #include "interfaces/scene.hpp" #include <yacppdic/factory.hpp> #include <memory> -#include <unordered_map> // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) class IGame @@ -20,11 +20,9 @@ public: virtual void on_update() noexcept = 0; virtual void on_exit() const noexcept = 0; - - [[nodiscard]] virtual auto get_input_config() const noexcept - -> std::unordered_map<char, std::shared_ptr<ICommand>> = 0; }; using IGameFactory = yacppdic::Factory<std::unique_ptr<IGame>( const std::shared_ptr<IScene> &scene, - const std::shared_ptr<ICursorController> &cursor_controller)>; + const std::shared_ptr<ICursorController> &cursor_controller, + const std::shared_ptr<IUserInputObserver> user_input_observer)>; diff --git a/src/interfaces/input.hpp b/src/interfaces/input.hpp index f93a8e2..8239e48 100644 --- a/src/interfaces/input.hpp +++ b/src/interfaces/input.hpp @@ -7,24 +7,16 @@ #include <memory> // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) -class IInputHandler : public IPublisher<char, std::nullptr_t> +class IUserInputObserver { public: - using Event = char; - using Context = std::nullptr_t; + using Key = char; - ~IInputHandler() noexcept override = default; + virtual ~IUserInputObserver() noexcept = default; - virtual void listen() const noexcept = 0; + virtual void listen() noexcept = 0; - void subscribe( - const Event &event, - const std::shared_ptr<ISubscriber<Context>> &subscriber) noexcept override = 0; + virtual bool is_key_pressed(Key key) noexcept = 0; - void notify_subscribers(const Event &event, const Context &context) - const noexcept override = 0; - - virtual void enter_raw_mode() noexcept = 0; - - virtual void leave_raw_mode() noexcept = 0; + virtual void clear_currently_pressed() noexcept = 0; }; diff --git a/src/interfaces/statusline.hpp b/src/interfaces/statusline.hpp index 2e97ed6..c66a2d3 100644 --- a/src/interfaces/statusline.hpp +++ b/src/interfaces/statusline.hpp @@ -14,7 +14,8 @@ enum StatusLineSection C = 2, D = 3, E = 4, - F = 5 + F = 5, + G = 6 }; // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) |