aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/bootstrap.cpp3
-rw-r--r--src/engine/game_initializer.cpp11
-rw-r--r--src/game/game.cpp41
-rw-r--r--src/game/game.hpp9
-rw-r--r--src/game/input_configurator.cpp33
-rw-r--r--src/game/input_configurator.hpp36
-rw-r--r--src/game/input_configurator.tpp17
-rw-r--r--src/interfaces/input_configurator.hpp9
-rw-r--r--src/util/function.hpp11
-rw-r--r--src/util/function.tpp75
11 files changed, 203 insertions, 43 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3351c07..e9b8fee 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -14,6 +14,7 @@ file(GLOB SOURCES
conversion.cpp
argument_parser.cpp
game/game.cpp
+ game/input_configurator.cpp
engine/game_initializer.cpp
engine/graphics/vector2.cpp
engine/graphics/bounds.cpp
diff --git a/src/bootstrap.cpp b/src/bootstrap.cpp
index abee66e..343f01b 100644
--- a/src/bootstrap.cpp
+++ b/src/bootstrap.cpp
@@ -6,6 +6,7 @@
#include "interfaces/game.hpp"
#include "interfaces/game_initializer.hpp"
#include "interfaces/input.hpp"
+#include "interfaces/input_configurator.hpp"
#include "interfaces/matrix.hpp"
#include "interfaces/randomization.hpp"
#include "interfaces/scene.hpp"
@@ -21,6 +22,7 @@
#include "engine/user/cursor.hpp"
#include "engine/user/input.hpp"
#include "game/game.hpp"
+#include "game/input_configurator.hpp"
#include "randomization/generator.hpp"
#include "randomization/seed_generator.hpp"
@@ -38,6 +40,7 @@ Container bootstrap()
container.bind<IInputHandler>().to<InputHandler>();
container.bind<CursorController>().to<CursorController>();
container.bind<IGameInitializer>().to<GameInitializer>();
+ container.bind<IInputConfigurator>().to<InputConfigurator>();
container.bind<IRandomNumberGeneratorFactory>().to_factory(
[](const unsigned int &seed)
diff --git a/src/engine/game_initializer.cpp b/src/engine/game_initializer.cpp
index 9430999..52e109a 100644
--- a/src/engine/game_initializer.cpp
+++ b/src/engine/game_initializer.cpp
@@ -1,5 +1,8 @@
#include "game_initializer.hpp"
+#include "util/function.hpp"
+
+#include <cstdlib>
#include <utility>
GameInitializer::GameInitializer(std::shared_ptr<IScene> scene,
@@ -14,8 +17,14 @@ GameInitializer::GameInitializer(std::shared_ptr<IScene> scene,
void GameInitializer::initialize()
{
_scene->enter();
-
_input_handler->enter_raw_mode();
+ std::atexit(normalize_lambda(
+ [this]()
+ {
+ _scene->leave();
+ _input_handler->leave_raw_mode();
+ }));
+
_game->run(*_scene, *_input_handler);
}
diff --git a/src/game/game.cpp b/src/game/game.cpp
index 559f9a0..0773f2c 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -2,46 +2,13 @@
#include <utility>
-Game::Game(std::shared_ptr<CursorController> cursor_controller)
- : _cursor_controller(std::move(cursor_controller))
+Game::Game(std::shared_ptr<IInputConfigurator> input_configurator)
+ : _input_configurator(std::move(input_configurator))
{
}
-void Game::run(IScene &scene, IInputHandler &input_handler)
+void Game::run(IScene & /*scene*/, IInputHandler &input_handler)
{
- input_handler.attach('q',
- [&input_handler, &scene]()
- {
- input_handler.leave_raw_mode();
- scene.leave();
- exit(EXIT_SUCCESS);
- });
-
- auto cursor_controller = _cursor_controller;
-
- input_handler.attach('k',
- [&cursor_controller]()
- {
- cursor_controller->move<Direction::UP>(1U);
- });
-
- input_handler.attach('j',
- [&cursor_controller]()
- {
- cursor_controller->move<Direction::DOWN>(1U);
- });
-
- input_handler.attach('h',
- [&cursor_controller]()
- {
- cursor_controller->move<Direction::LEFT>(1U);
- });
-
- input_handler.attach('l',
- [&cursor_controller]()
- {
- cursor_controller->move<Direction::RIGHT>(1U);
- });
-
+ _input_configurator->configure(input_handler);
input_handler.listen();
}
diff --git a/src/game/game.hpp b/src/game/game.hpp
index c52399d..ea8145a 100644
--- a/src/game/game.hpp
+++ b/src/game/game.hpp
@@ -3,19 +3,18 @@
#include "DI/auto_wirable.hpp"
#include "interfaces/game.hpp"
#include "interfaces/input.hpp"
+#include "interfaces/input_configurator.hpp"
#include "interfaces/scene.hpp"
-#include "engine/user/cursor.hpp"
-
#include <memory>
-class Game : public IGame, public AutoWirable<IGame, Game, CursorController>
+class Game : public IGame, public AutoWirable<IGame, Game, IInputConfigurator>
{
public:
- explicit Game(std::shared_ptr<CursorController> cursor_controller);
+ explicit Game(std::shared_ptr<IInputConfigurator> input_configurator);
void run(IScene &scene, IInputHandler &input_handler) override;
private:
- std::shared_ptr<CursorController> _cursor_controller;
+ std::shared_ptr<IInputConfigurator> _input_configurator;
};
diff --git a/src/game/input_configurator.cpp b/src/game/input_configurator.cpp
new file mode 100644
index 0000000..4daee21
--- /dev/null
+++ b/src/game/input_configurator.cpp
@@ -0,0 +1,33 @@
+#include "input_configurator.hpp"
+
+namespace InputActions
+{
+
+void exit_success()
+{
+ exit(EXIT_SUCCESS);
+}
+
+} // namespace InputActions
+
+InputConfigurator::InputConfigurator(std::shared_ptr<CursorController> cursor_controller)
+ : _cursor_controller(std::move(cursor_controller))
+{
+}
+
+void InputConfigurator::configure(IInputHandler &input_handler)
+{
+ input_handler.attach('q', InputActions::exit_success);
+
+ input_handler.attach('k',
+ InputActions::move_cursor<Direction::UP>(*_cursor_controller));
+
+ input_handler.attach('j',
+ InputActions::move_cursor<Direction::DOWN>(*_cursor_controller));
+
+ input_handler.attach('h',
+ InputActions::move_cursor<Direction::LEFT>(*_cursor_controller));
+
+ input_handler.attach(
+ 'l', InputActions::move_cursor<Direction::RIGHT>(*_cursor_controller));
+}
diff --git a/src/game/input_configurator.hpp b/src/game/input_configurator.hpp
new file mode 100644
index 0000000..217c21e
--- /dev/null
+++ b/src/game/input_configurator.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "DI/auto_wirable.hpp"
+#include "interfaces/direction.hpp"
+#include "interfaces/input.hpp"
+#include "interfaces/input_configurator.hpp"
+
+#include "engine/user/cursor.hpp"
+
+#include <array>
+#include <memory>
+
+namespace InputActions
+{
+
+template <Direction::value_type direction>
+auto move_cursor(CursorController cursor_controller);
+
+void exit_success();
+
+} // namespace InputActions
+
+class InputConfigurator
+ : public IInputConfigurator,
+ public AutoWirable<IInputConfigurator, InputConfigurator, CursorController>
+{
+public:
+ explicit InputConfigurator(std::shared_ptr<CursorController> cursor_controller);
+
+ void configure(IInputHandler &input_handler) override;
+
+private:
+ std::shared_ptr<CursorController> _cursor_controller;
+};
+
+#include "input_configurator.tpp"
diff --git a/src/game/input_configurator.tpp b/src/game/input_configurator.tpp
new file mode 100644
index 0000000..f3c9482
--- /dev/null
+++ b/src/game/input_configurator.tpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "input_configurator.hpp"
+
+namespace InputActions
+{
+
+template <Direction::value_type direction>
+auto move_cursor(CursorController cursor_controller)
+{
+ return [cursor_controller]()
+ {
+ cursor_controller.move<direction>(1U);
+ };
+}
+
+} // namespace InputActions
diff --git a/src/interfaces/input_configurator.hpp b/src/interfaces/input_configurator.hpp
new file mode 100644
index 0000000..2bfe51e
--- /dev/null
+++ b/src/interfaces/input_configurator.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "interfaces/input.hpp"
+
+class IInputConfigurator
+{
+public:
+ virtual void configure(IInputHandler &input_handler) = 0;
+};
diff --git a/src/util/function.hpp b/src/util/function.hpp
new file mode 100644
index 0000000..13f5356
--- /dev/null
+++ b/src/util/function.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+template <typename>
+struct Signature
+{
+};
+
+template <typename Function>
+constexpr auto normalize_lambda(Function &&func) noexcept;
+
+#include "function.tpp"
diff --git a/src/util/function.tpp b/src/util/function.tpp
new file mode 100644
index 0000000..6ff939b
--- /dev/null
+++ b/src/util/function.tpp
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "function.hpp"
+
+#include <utility>
+
+template <typename>
+struct remove_cv_seq;
+
+template <typename Return, typename... Args>
+struct remove_cv_seq<Return(Args...)>
+{
+ using type = Return(Args...);
+};
+
+template <typename Return, typename... Args>
+struct remove_cv_seq<Return(Args...) const>
+{
+ using type = Return(Args...);
+};
+
+template <typename Return, typename... Args>
+struct remove_cv_seq<Return(Args...) &>
+{
+ using type = Return(Args...);
+};
+
+template <typename Function>
+constexpr inline auto extract_signature(Function * /*unused*/) noexcept
+{
+ return Signature<typename remove_cv_seq<Function>::type>();
+}
+
+template <typename Class, typename Function>
+constexpr inline auto extract_signature(Function Class::* /*unused*/) noexcept
+{
+ return Signature<typename remove_cv_seq<Function>::type>();
+}
+
+template <typename Function>
+constexpr inline auto extract_signature(Function const & /*unused*/) noexcept
+ -> decltype(&Function::operator(), extract_signature(&Function::operator()))
+{
+ return extract_signature(&Function::operator());
+}
+
+template <typename Function, typename Return, typename... Args>
+inline auto get_normalized_lambda(Function &&func,
+ Signature<Return(Args...)> /*unused*/) noexcept
+{
+ // Static copy of func. This will make it accessible for the lambda without using a
+ // lamda capture
+ static auto static_func = Function(std::forward<Function>(func));
+
+ return +[](Args... args) noexcept(
+ noexcept(std::declval<Function>()(std::forward<Args>(args)...))) -> Return
+ {
+ return static_func(std::forward<Args>(args)...);
+ };
+}
+
+/**
+ * Normalizes the type signature of a lambda function.
+ *
+ * This will make a lambda with captures passable to other functions.
+ *
+ * @param func A lambda function
+ * @returns The lambda function normalized.
+ */
+template <typename Function>
+constexpr auto normalize_lambda(Function &&func) noexcept
+{
+ return get_normalized_lambda(std::forward<Function>(func),
+ extract_signature(std::forward<Function>(func)));
+}