From ede689d23e57c9b701ab19aa9112a0b2368865c9 Mon Sep 17 00:00:00 2001 From: HampusM Date: Mon, 28 Feb 2022 21:30:30 +0100 Subject: feat: add input handler & quitting with 'q' --- src/CMakeLists.txt | 1 + src/bootstrap.cpp | 3 ++ src/engine/user/input.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++ src/engine/user/input.hpp | 31 +++++++++++++++++++++ src/game/game.cpp | 23 ++++++++++++---- src/game/game.hpp | 7 +++-- src/interfaces/input.hpp | 17 ++++++++++++ src/interfaces/observable.hpp | 16 +++++++++++ 8 files changed, 155 insertions(+), 7 deletions(-) create mode 100644 src/engine/user/input.cpp create mode 100644 src/engine/user/input.hpp create mode 100644 src/interfaces/input.hpp create mode 100644 src/interfaces/observable.hpp (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 385283d..54793b0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,6 +18,7 @@ file(GLOB SOURCES engine/graphics/bounds.cpp engine/graphics/scene.cpp engine/graphics/string_matrix.cpp + engine/user/input.cpp randomization/generator.cpp randomization/seed_generator.cpp DI/object_type.cpp) diff --git a/src/bootstrap.cpp b/src/bootstrap.cpp index 8a8aa25..6b4a954 100644 --- a/src/bootstrap.cpp +++ b/src/bootstrap.cpp @@ -4,6 +4,7 @@ #include "interfaces/argument_parser.hpp" #include "interfaces/bounds.hpp" #include "interfaces/game.hpp" +#include "interfaces/input.hpp" #include "interfaces/matrix.hpp" #include "interfaces/randomization.hpp" #include "interfaces/scene.hpp" @@ -15,6 +16,7 @@ #include "engine/graphics/scene.hpp" #include "engine/graphics/string_matrix.hpp" #include "engine/graphics/vector2.hpp" +#include "engine/user/input.hpp" #include "game/game.hpp" #include "randomization/generator.hpp" #include "randomization/seed_generator.hpp" @@ -30,6 +32,7 @@ Container bootstrap() container.bind().to(); container.bind().to(); container.bind().to(); + container.bind().to(); container.bind().to_factory( [](const unsigned int &seed) diff --git a/src/engine/user/input.cpp b/src/engine/user/input.cpp new file mode 100644 index 0000000..e68f303 --- /dev/null +++ b/src/engine/user/input.cpp @@ -0,0 +1,64 @@ +#include "input.hpp" + +#include + +void InputHandler::listen() const +{ + char character = 0; + + while (read(STDIN_FILENO, &character, 1) == 1) + { + notify(character); + } +} + +void InputHandler::attach(const char &event, Callback callback) +{ + if (_key_observers.count(event) == 0) + { + _key_observers[event] = std::vector(); + } + + _key_observers[event].push_back(callback); +} + +void InputHandler::notify(const char &event) const +{ + if (_key_observers.count(event) == 0) + { + return; + } + + for (const auto &observer : _key_observers.at(event)) + { + observer(); + } +} + +void InputHandler::enter_raw_mode() +{ + if (_original_termios == nullptr) + { + _original_termios = std::make_shared(); + } + + tcgetattr(STDIN_FILENO, _original_termios.get()); + + auto raw_termios = termios(*_original_termios); + + raw_termios.c_lflag &= static_cast(~(ECHO | ICANON | ISIG)); + + tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw_termios); +} + +void InputHandler::leave_raw_mode() +{ + if (_original_termios == nullptr) + { + return; + } + + tcsetattr(STDIN_FILENO, TCSAFLUSH, _original_termios.get()); + + _original_termios = nullptr; +} diff --git a/src/engine/user/input.hpp b/src/engine/user/input.hpp new file mode 100644 index 0000000..f48ab86 --- /dev/null +++ b/src/engine/user/input.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "DI/auto_wirable.hpp" +#include "interfaces/input.hpp" +#include "interfaces/observable.hpp" + +#include +#include +#include +#include + +class InputHandler : public IInputHandler, public AutoWirable +{ +public: + InputHandler() = default; + + void listen() const override; + + void attach(const char &event, Callback callback) override; + + void notify(const char &event) const override; + + void enter_raw_mode() override; + + void leave_raw_mode() override; + +private: + std::unordered_map> _key_observers; + + std::shared_ptr _original_termios = nullptr; +}; diff --git a/src/game/game.cpp b/src/game/game.cpp index 2c99c6a..2b09470 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -1,15 +1,28 @@ #include "game.hpp" -#include -#include - -Game::Game(std::shared_ptr scene) : _scene(std::move(scene)) {} +Game::Game(std::shared_ptr scene, std::shared_ptr input_handler) + : _scene(std::move(scene)), _input_handler(std::move(input_handler)) +{ +} void Game::run() { _scene->enter(); - std::this_thread::sleep_for(std::chrono::seconds(3)); + _input_handler->enter_raw_mode(); + + auto scene = _scene; + auto input_handler = _input_handler; + + _input_handler->attach('q', + [&input_handler, &scene]() + { + input_handler->leave_raw_mode(); + scene->leave(); + exit(EXIT_SUCCESS); + }); + + _input_handler->listen(); _scene->leave(); } diff --git a/src/game/game.hpp b/src/game/game.hpp index e7d91d6..bc37c91 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -2,17 +2,20 @@ #include "DI/auto_wirable.hpp" #include "interfaces/game.hpp" +#include "interfaces/input.hpp" #include "interfaces/scene.hpp" #include -class Game : public IGame, public AutoWirable +class Game : public IGame, public AutoWirable { public: - explicit Game(std::shared_ptr scene); + explicit Game(std::shared_ptr scene, + std::shared_ptr input_handler); void run() override; private: std::shared_ptr _scene; + std::shared_ptr _input_handler; }; diff --git a/src/interfaces/input.hpp b/src/interfaces/input.hpp new file mode 100644 index 0000000..956ec4f --- /dev/null +++ b/src/interfaces/input.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "interfaces/observable.hpp" + +class IInputHandler : public IObservable +{ +public: + void listen() const override = 0; + + void attach(const char &event, Callback callback) override = 0; + + void notify(const char &event) const override = 0; + + virtual void enter_raw_mode() = 0; + + virtual void leave_raw_mode() = 0; +}; diff --git a/src/interfaces/observable.hpp b/src/interfaces/observable.hpp new file mode 100644 index 0000000..ca8ffda --- /dev/null +++ b/src/interfaces/observable.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include + +using Callback = std::function; + +template +class IObservable +{ +public: + virtual void listen() const = 0; + + virtual void attach(const Event &event, Callback callback) = 0; + + virtual void notify(const Event &event) const = 0; +}; -- cgit v1.2.3-18-g5258