aboutsummaryrefslogtreecommitdiff
path: root/src/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/data/bounds.cpp10
-rw-r--r--src/engine/data/bounds.hpp4
-rw-r--r--src/engine/data/vector2.cpp30
-rw-r--r--src/engine/data/vector2.hpp10
-rw-r--r--src/engine/engine.cpp67
-rw-r--r--src/engine/engine.hpp37
-rw-r--r--src/engine/game_initializer.cpp32
-rw-r--r--src/engine/game_initializer.hpp26
-rw-r--r--src/engine/graphics/window.cpp13
-rw-r--r--src/engine/graphics/window.hpp14
-rw-r--r--src/engine/user/cursor.cpp39
-rw-r--r--src/engine/user/cursor.hpp8
12 files changed, 196 insertions, 94 deletions
diff --git a/src/engine/data/bounds.cpp b/src/engine/data/bounds.cpp
index acd98af..41b6dc0 100644
--- a/src/engine/data/bounds.cpp
+++ b/src/engine/data/bounds.cpp
@@ -32,11 +32,21 @@ CoordsValidation Bounds::validate_coords(const Vector2 &coords) const noexcept
return CoordsValidation::X_HIGH;
}
+ if (static_cast<uint32_t>(coords.get_x()) <= 0)
+ {
+ return CoordsValidation::X_LOW;
+ }
+
if (static_cast<uint32_t>(coords.get_y()) >= _height)
{
return CoordsValidation::Y_HIGH;
}
+ if (static_cast<uint32_t>(coords.get_y()) <= 0)
+ {
+ return CoordsValidation::Y_LOW;
+ }
+
return CoordsValidation::VALID;
}
diff --git a/src/engine/data/bounds.hpp b/src/engine/data/bounds.hpp
index b29005e..9b72f59 100644
--- a/src/engine/data/bounds.hpp
+++ b/src/engine/data/bounds.hpp
@@ -8,7 +8,9 @@ enum CoordsValidation
{
VALID,
X_HIGH,
- Y_HIGH
+ X_LOW,
+ Y_HIGH,
+ Y_LOW
};
struct BoundsOptions
diff --git a/src/engine/data/vector2.cpp b/src/engine/data/vector2.cpp
index f91afa8..04cc42e 100644
--- a/src/engine/data/vector2.cpp
+++ b/src/engine/data/vector2.cpp
@@ -24,6 +24,12 @@ void Vector2::set_y(Vector2::Value y) noexcept
_y = y;
}
+Vector2 Vector2::to_direction(const Vector2 &direction,
+ Vector2::Value amount) const noexcept
+{
+ return *this + (direction * Vector2({.x = amount, .y = amount}));
+}
+
const Vector2 &Vector2::operator+=(const Vector2 &vector2) noexcept
{
_x += vector2._x;
@@ -40,6 +46,26 @@ const Vector2 &Vector2::operator-=(const Vector2 &vector2) noexcept
return *this;
}
+Vector2 Vector2::operator+(const Vector2 &vector2) const noexcept
+{
+ auto new_vector2 = Vector2(*this);
+
+ new_vector2._x += vector2._x;
+ new_vector2._y += vector2._y;
+
+ return new_vector2;
+}
+
+Vector2 Vector2::operator*(const Vector2 &vector2) const noexcept
+{
+ auto new_vector2 = Vector2(*this);
+
+ new_vector2._x *= vector2._x;
+ new_vector2._y *= vector2._y;
+
+ return new_vector2;
+}
+
bool Vector2::operator==(const Vector2 &vector2) const noexcept
{
return _x == vector2._x && _y == vector2._y;
@@ -47,12 +73,12 @@ bool Vector2::operator==(const Vector2 &vector2) const noexcept
Vector2 Vector2::up() noexcept
{
- return Vector2({.x = 0, .y = 1});
+ return Vector2({.x = 0, .y = -1});
}
Vector2 Vector2::down() noexcept
{
- return Vector2({.x = 0, .y = -1});
+ return Vector2({.x = 0, .y = 1});
}
Vector2 Vector2::left() noexcept
diff --git a/src/engine/data/vector2.hpp b/src/engine/data/vector2.hpp
index 49e5d85..e835e65 100644
--- a/src/engine/data/vector2.hpp
+++ b/src/engine/data/vector2.hpp
@@ -27,18 +27,24 @@ public:
void set_y(Value y) noexcept;
+ [[nodiscard]] Vector2 to_direction(const Vector2 &direction,
+ Vector2::Value amount) const noexcept;
+
const Vector2 &operator+=(const Vector2 &vector2) noexcept;
const Vector2 &operator-=(const Vector2 &vector2) noexcept;
+ Vector2 operator+(const Vector2 &vector2) const noexcept;
+ Vector2 operator*(const Vector2 &vector2) const noexcept;
+
bool operator==(const Vector2 &vector2) const noexcept;
/**
- * Returns Vector2({.x = 0, .y = 1})
+ * Returns Vector2({.x = 0, .y = -1})
*/
static Vector2 up() noexcept;
/**
- * Returns Vector2({.x = 0, .y = -1})
+ * Returns Vector2({.x = 0, .y = 1})
*/
static Vector2 down() noexcept;
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp
new file mode 100644
index 0000000..0227d5c
--- /dev/null
+++ b/src/engine/engine.cpp
@@ -0,0 +1,67 @@
+#include "engine.hpp"
+
+#include "input_actions.hpp"
+
+#include "util/function.hpp"
+
+#include <cstdlib>
+#include <utility>
+
+CLIGameEngine::CLIGameEngine(IGameFactory game_factory, ISceneFactory scene_factory,
+ std::shared_ptr<IInputHandler> input_handler,
+ std::shared_ptr<ICursorController> cursor_controller,
+ std::shared_ptr<IWindow> window) noexcept
+ : _game_factory(game_factory),
+ _scene_factory(scene_factory),
+ _input_handler(std::move(input_handler)),
+ _cursor_controller(std::move(cursor_controller)),
+ _window(std::move(window))
+{
+}
+
+void CLIGameEngine::start() noexcept
+{
+ auto scene = _scene_factory();
+
+ scene->enter();
+ _input_handler->enter_raw_mode();
+
+ const auto window_size = _window->size();
+
+ const auto center_position =
+ Vector2({.x = static_cast<Vector2::Value>(window_size.get_width()) / 2,
+ .y = static_cast<Vector2::Value>(window_size.get_height()) / 2});
+
+ _cursor_controller->move_to(center_position);
+
+ std::atexit(normalize_lambda(
+ [scene, this]()
+ {
+ scene->leave();
+ _input_handler->leave_raw_mode();
+ }));
+
+ const std::unordered_map<char, Callback> input_config = {
+ {'q', InputActions::exit_success},
+ {'k', InputActions::move_cursor(Vector2::up(), _cursor_controller, _window)},
+ {'j', InputActions::move_cursor(Vector2::down(), _cursor_controller, _window)},
+ {'h', InputActions::move_cursor(Vector2::left(), _cursor_controller, _window)},
+ {'l', InputActions::move_cursor(Vector2::right(), _cursor_controller, _window)}};
+
+ _configure_input(input_config);
+
+ _input_handler->listen();
+
+ auto game = _game_factory();
+
+ game->run();
+}
+
+void CLIGameEngine::_configure_input(
+ const std::unordered_map<char, Callback> &input_config)
+{
+ for (const auto &config_pair : input_config)
+ {
+ _input_handler->attach(config_pair.first, config_pair.second);
+ }
+}
diff --git a/src/engine/engine.hpp b/src/engine/engine.hpp
new file mode 100644
index 0000000..504fc28
--- /dev/null
+++ b/src/engine/engine.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "DI/auto_wirable.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"
+
+#include <memory>
+#include <unordered_map>
+
+class CLIGameEngine
+ : public ICLIGameEngine,
+ public AutoWirable<ICLIGameEngine, CLIGameEngine, IGameFactory, ISceneFactory,
+ IInputHandler, ICursorController, IWindow>
+{
+public:
+ CLIGameEngine(IGameFactory game_factory, ISceneFactory scene_factory,
+ std::shared_ptr<IInputHandler> input_handler,
+ std::shared_ptr<ICursorController> cursor_controller,
+ std::shared_ptr<IWindow> window) noexcept;
+
+ void start() noexcept override;
+
+private:
+ IGameFactory _game_factory;
+ ISceneFactory _scene_factory;
+
+ std::shared_ptr<IInputHandler> _input_handler;
+ std::shared_ptr<ICursorController> _cursor_controller;
+ std::shared_ptr<IWindow> _window;
+
+ void _configure_input(const std::unordered_map<char, Callback> &input_config);
+};
diff --git a/src/engine/game_initializer.cpp b/src/engine/game_initializer.cpp
deleted file mode 100644
index 13d9ba0..0000000
--- a/src/engine/game_initializer.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "game_initializer.hpp"
-
-#include "util/function.hpp"
-
-#include <cstdlib>
-#include <utility>
-
-GameInitializer::GameInitializer(std::shared_ptr<IScene> scene,
- std::shared_ptr<IInputHandler> input_handler,
- IGameFactory game_factory)
- : _scene(std::move(scene)),
- _input_handler(std::move(input_handler)),
- _game_factory(game_factory)
-{
-}
-
-void GameInitializer::initialize()
-{
- _scene->enter();
- _input_handler->enter_raw_mode();
-
- std::atexit(normalize_lambda(
- [this]()
- {
- _scene->leave();
- _input_handler->leave_raw_mode();
- }));
-
- auto game = _game_factory();
-
- game->run(*_scene, *_input_handler);
-}
diff --git a/src/engine/game_initializer.hpp b/src/engine/game_initializer.hpp
deleted file mode 100644
index 2f63e0f..0000000
--- a/src/engine/game_initializer.hpp
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-
-#include "DI/auto_wirable.hpp"
-#include "interfaces/game.hpp"
-#include "interfaces/game_initializer.hpp"
-#include "interfaces/input.hpp"
-#include "interfaces/scene.hpp"
-
-#include <memory>
-
-class GameInitializer : public IGameInitializer,
- public AutoWirable<IGameInitializer, GameInitializer, IScene,
- IInputHandler, IGameFactory>
-{
-public:
- GameInitializer(std::shared_ptr<IScene> scene,
- std::shared_ptr<IInputHandler> input_handler,
- IGameFactory game_factory);
-
- void initialize() override;
-
-private:
- std::shared_ptr<IScene> _scene;
- std::shared_ptr<IInputHandler> _input_handler;
- IGameFactory _game_factory;
-};
diff --git a/src/engine/graphics/window.cpp b/src/engine/graphics/window.cpp
new file mode 100644
index 0000000..d6bae0c
--- /dev/null
+++ b/src/engine/graphics/window.cpp
@@ -0,0 +1,13 @@
+#include "window.hpp"
+
+#include <sys/ioctl.h>
+
+Bounds Window::size() const noexcept
+{
+ winsize window_size = {};
+
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
+ ioctl(0, TIOCGWINSZ, &window_size);
+
+ return Bounds({window_size.ws_col, window_size.ws_row});
+}
diff --git a/src/engine/graphics/window.hpp b/src/engine/graphics/window.hpp
new file mode 100644
index 0000000..c9a9c70
--- /dev/null
+++ b/src/engine/graphics/window.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "DI/auto_wirable.hpp"
+#include "interfaces/window.hpp"
+
+#include "engine/data/bounds.hpp"
+
+class Window : public IWindow, public AutoWirable<IWindow, Window>
+{
+public:
+ Window() noexcept = default;
+
+ [[nodiscard]] Bounds size() const noexcept override;
+};
diff --git a/src/engine/user/cursor.cpp b/src/engine/user/cursor.cpp
index 39fef23..663d56a 100644
--- a/src/engine/user/cursor.cpp
+++ b/src/engine/user/cursor.cpp
@@ -5,32 +5,17 @@
#include <cstdlib>
#include <iostream>
-CursorController::CursorController() : _position(_request_position()) {}
+CursorController::CursorController() : _position({.x = 0, .y = 0}) {}
void CursorController::move(const Vector2 &direction, const uint32_t &amount) noexcept
{
- auto format = direction_format_map.at(direction);
+ auto direction_format = direction_format_map.at(direction);
- fmt::print(fmt::runtime(format.data()), fmt::arg("esc", ESC),
+ fmt::print(fmt::runtime(direction_format.data()), fmt::arg("esc", ESC),
fmt::arg("amount", amount));
std::cout.flush();
- if (direction == Vector2::up())
- {
- _position.set_y(_position.get_y() + static_cast<int>(amount));
- }
- else if (direction == Vector2::down())
- {
- _position.set_y(_position.get_y() - static_cast<int>(amount));
- }
- else if (direction == Vector2::left())
- {
- _position.set_x(_position.get_x() - static_cast<int>(amount));
- }
- else if (direction == Vector2::right())
- {
- _position.set_x(_position.get_x() + static_cast<int>(amount));
- }
+ _position = _position.to_direction(direction, static_cast<Vector2::Value>(amount));
}
void CursorController::move_to(const Vector2 &position) noexcept
@@ -53,13 +38,7 @@ void CursorController::hide()
std::cout.flush();
}
-void CursorController::show()
-{
- fmt::print(CURSOR_VISIBLE, fmt::arg("esc", ESC));
- std::cout.flush();
-}
-
-Vector2 CursorController::_request_position() noexcept
+void CursorController::ensure_position() noexcept
{
fmt::print(REQUEST_CURSOR_POSITION, fmt::arg("esc", ESC));
std::cout.flush();
@@ -69,5 +48,11 @@ Vector2 CursorController::_request_position() noexcept
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
scanf("\033[%u;%uR", &vector2_options.y, &vector2_options.x);
- return Vector2(vector2_options);
+ _position = Vector2(vector2_options);
+}
+
+void CursorController::show()
+{
+ fmt::print(CURSOR_VISIBLE, fmt::arg("esc", ESC));
+ std::cout.flush();
}
diff --git a/src/engine/user/cursor.hpp b/src/engine/user/cursor.hpp
index 977bfdf..c591235 100644
--- a/src/engine/user/cursor.hpp
+++ b/src/engine/user/cursor.hpp
@@ -39,14 +39,14 @@ public:
void move_to(const Vector2 &position) noexcept override;
+ [[nodiscard]] Vector2 where() const noexcept override;
+
+ void ensure_position() noexcept override;
+
static void hide();
static void show();
- [[nodiscard]] Vector2 where() const noexcept override;
-
private:
Vector2 _position;
-
- [[nodiscard]] static Vector2 _request_position() noexcept;
};