diff options
Diffstat (limited to 'src/game')
-rw-r--r-- | src/game/cursor_listener.cpp | 14 | ||||
-rw-r--r-- | src/game/cursor_listener.hpp | 19 | ||||
-rw-r--r-- | src/game/game.cpp | 26 | ||||
-rw-r--r-- | src/game/game.hpp | 21 | ||||
-rw-r--r-- | src/game/generation_tracker.cpp | 18 | ||||
-rw-r--r-- | src/game/generation_tracker.hpp | 22 | ||||
-rw-r--r-- | src/game/status_updater.cpp | 25 | ||||
-rw-r--r-- | src/game/status_updater.hpp | 24 | ||||
-rw-r--r-- | src/game/statusline.cpp | 102 | ||||
-rw-r--r-- | src/game/statusline.hpp | 41 |
10 files changed, 267 insertions, 45 deletions
diff --git a/src/game/cursor_listener.cpp b/src/game/cursor_listener.cpp deleted file mode 100644 index c815f08..0000000 --- a/src/game/cursor_listener.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "cursor_listener.hpp" - -#include <fmt/core.h> -#include <utility> - -CursorListener::CursorListener(std::shared_ptr<IScene> scene) noexcept - : _scene(std::move(scene)) -{ -} - -void CursorListener::update(const Vector2 &context) noexcept -{ - _scene->write_status(fmt::format("X: {} Y {}", context.get_x(), context.get_y())); -} diff --git a/src/game/cursor_listener.hpp b/src/game/cursor_listener.hpp deleted file mode 100644 index c74bb3d..0000000 --- a/src/game/cursor_listener.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "interfaces/scene.hpp" -#include "interfaces/subscriber.hpp" - -#include "engine/data/vector2.hpp" - -#include <memory> - -class CursorListener : public ISubscriber<Vector2> -{ -public: - explicit CursorListener(std::shared_ptr<IScene> scene) noexcept; - - void update(const Vector2 &context) noexcept override; - -private: - std::shared_ptr<IScene> _scene; -}; diff --git a/src/game/game.cpp b/src/game/game.cpp index f788d15..6632c08 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -3,22 +3,31 @@ #include "commands/insert_cell.hpp" #include "commands/move_cursor.hpp" #include "commands/quit.hpp" -#include "game/cursor_listener.hpp" +#include "commands/toggle_pause.hpp" #include <fmt/core.h> #include <iostream> +#include <utility> -Game::Game(const std::shared_ptr<IWindow> &window, const std::shared_ptr<IScene> &scene, - const std::shared_ptr<ICursorController> &cursor_controller) noexcept - : _window(window), _scene(scene), _cursor_controller(cursor_controller) +Game::Game(std::shared_ptr<IWindow> window, std::shared_ptr<IScene> scene, + std::shared_ptr<ICursorController> cursor_controller, + std::shared_ptr<IStatusLine> statusline, + std::shared_ptr<IGenerationTracker> generation_tracker, + std::shared_ptr<IStatusUpdater> status_updater) noexcept + : _window(std::move(window)), + _scene(std::move(scene)), + _cursor_controller(std::move(cursor_controller)), + _statusline(std::move(statusline)), + _generation_tracker(std::move(generation_tracker)), + _status_updater(std::move(status_updater)) { } void Game::on_start() noexcept { - auto cursor_listener = std::make_shared<CursorListener>(_scene); + _statusline->initialize_background(); - _cursor_controller->subscribe(CursorEvent::POSITION_CHANGE, cursor_listener); + _cursor_controller->subscribe(CursorEvent::POSITION_CHANGE, _status_updater); const auto window_size = _window->size(); @@ -28,9 +37,11 @@ void Game::on_start() noexcept _cursor_controller->move_to(center_position); - cursor_listener->update(center_position); + _status_updater->update(center_position); } +void Game::on_update() noexcept {} + void Game::on_exit() const noexcept { for (auto row : *_scene->get_matrix()) @@ -51,6 +62,7 @@ Game::get_input_config() const noexcept { return {{'q', std::make_shared<QuitCommand>()}, {'i', std::make_shared<InsertCellCommand>(_cursor_controller, _scene)}, + {'p', std::make_shared<TogglePauseCommand>(_generation_tracker, _statusline)}, {'k', std::make_shared<MoveCursorCommand>(Vector2::up(), _cursor_controller, _window)}, {'j', std::make_shared<MoveCursorCommand>(Vector2::down(), _cursor_controller, diff --git a/src/game/game.hpp b/src/game/game.hpp index 2493a42..5894a01 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -2,7 +2,10 @@ #include "interfaces/cursor.hpp" #include "interfaces/game.hpp" +#include "interfaces/generation_tracker.hpp" #include "interfaces/scene.hpp" +#include "interfaces/status_updater.hpp" +#include "interfaces/statusline.hpp" #include "interfaces/window.hpp" #include <memory> @@ -10,18 +13,26 @@ class Game : public IGame { public: - Game(const std::shared_ptr<IWindow> &window, const std::shared_ptr<IScene> &scene, - const std::shared_ptr<ICursorController> &cursor_controller) noexcept; + Game(std::shared_ptr<IWindow> window, std::shared_ptr<IScene> scene, + std::shared_ptr<ICursorController> cursor_controller, + std::shared_ptr<IStatusLine> statusline, + std::shared_ptr<IGenerationTracker> generation_tracker, + std::shared_ptr<IStatusUpdater> status_updater) noexcept; void on_start() noexcept override; + void on_update() noexcept override; + void on_exit() const noexcept override; [[nodiscard]] std::unordered_map<char, std::shared_ptr<ICommand>> get_input_config() const noexcept override; private: - const std::shared_ptr<IWindow> &_window; - const std::shared_ptr<IScene> &_scene; - const std::shared_ptr<ICursorController> &_cursor_controller; + std::shared_ptr<IWindow> _window; + std::shared_ptr<IScene> _scene; + std::shared_ptr<ICursorController> _cursor_controller; + std::shared_ptr<IStatusLine> _statusline; + std::shared_ptr<IGenerationTracker> _generation_tracker; + std::shared_ptr<IStatusUpdater> _status_updater; }; diff --git a/src/game/generation_tracker.cpp b/src/game/generation_tracker.cpp new file mode 100644 index 0000000..0e137cb --- /dev/null +++ b/src/game/generation_tracker.cpp @@ -0,0 +1,18 @@ +#include "generation_tracker.hpp" + +GenerationTracker::GenerationTracker(bool is_paused) noexcept : _is_paused(is_paused) {} + +uint32_t GenerationTracker::get_current_generation() const noexcept +{ + return _current_generation; +} + +bool GenerationTracker::get_is_paused() const noexcept +{ + return _is_paused; +} + +void GenerationTracker::set_is_paused(bool is_paused) noexcept +{ + _is_paused = is_paused; +} diff --git a/src/game/generation_tracker.hpp b/src/game/generation_tracker.hpp new file mode 100644 index 0000000..0e59751 --- /dev/null +++ b/src/game/generation_tracker.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "interfaces/generation_tracker.hpp" + +#include <cstdint> + +class GenerationTracker : public IGenerationTracker +{ +public: + explicit GenerationTracker(bool is_paused) noexcept; + + [[nodiscard]] uint32_t get_current_generation() const noexcept override; + + [[nodiscard]] bool get_is_paused() const noexcept override; + + void set_is_paused(bool is_paused) noexcept override; + +private: + uint32_t _current_generation = 0U; + + bool _is_paused; +}; diff --git a/src/game/status_updater.cpp b/src/game/status_updater.cpp new file mode 100644 index 0000000..18c535e --- /dev/null +++ b/src/game/status_updater.cpp @@ -0,0 +1,25 @@ +#include "status_updater.hpp" + +#include <fmt/core.h> +#include <utility> + +StatusUpdater::StatusUpdater( + std::shared_ptr<IStatusLine> statusline, + std::shared_ptr<IGenerationTracker> generation_tracker) noexcept + : _statusline(std::move(statusline)), + _generation_tracker(std::move(generation_tracker)) +{ +} + +void StatusUpdater::update(const Vector2 &context) noexcept +{ + _statusline->set_status( + StatusLineSection::A, + fmt::format("X: {} Y {}", context.get_x(), context.get_y())); + + _statusline->set_status( + StatusLineSection::B, + fmt::format("Paused: {} Generation: {}", + _generation_tracker->get_is_paused() ? "yes" : "no", + _generation_tracker->get_current_generation())); +} diff --git a/src/game/status_updater.hpp b/src/game/status_updater.hpp new file mode 100644 index 0000000..3b76d3b --- /dev/null +++ b/src/game/status_updater.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "interfaces/generation_tracker.hpp" +#include "interfaces/status_updater.hpp" +#include "interfaces/statusline.hpp" +#include "interfaces/subscriber.hpp" + +#include "engine/data/vector2.hpp" + +#include <memory> + +class StatusUpdater : public IStatusUpdater +{ +public: + explicit StatusUpdater( + std::shared_ptr<IStatusLine> statusline, + std::shared_ptr<IGenerationTracker> generation_tracker) noexcept; + + void update(const Vector2 &context) noexcept override; + +private: + std::shared_ptr<IStatusLine> _statusline; + std::shared_ptr<IGenerationTracker> _generation_tracker; +}; diff --git a/src/game/statusline.cpp b/src/game/statusline.cpp new file mode 100644 index 0000000..377fa75 --- /dev/null +++ b/src/game/statusline.cpp @@ -0,0 +1,102 @@ +#include "statusline.hpp" + +#include "engine/escape.hpp" +#include "util/color.hpp" + +#include <iostream> +#include <string> +#include <utility> + +StatusLine::StatusLine(std::shared_ptr<ICursorController> cursor_controller, + std::shared_ptr<IWindow> window) noexcept + : _cursor_controller(std::move(cursor_controller)), _window(std::move(window)) +{ + constexpr uint32_t SECTION_A_LENGTH = 20; + constexpr uint32_t SECTION_B_LENGTH = 15; + + _sections_lengths[StatusLineSection::A] = SECTION_A_LENGTH; + _sections_lengths[StatusLineSection::B] = SECTION_B_LENGTH; +} + +void StatusLine::initialize_background() noexcept +{ + const auto previous_position = _move_to_statusline(0); + + auto background_color = get_background_esc_seq(STATUSBAR_COLOR); + + fmt::print("{}{}", background_color, std::string(_window->size().get_width(), ' ')); + fmt::print(RESET_ALL_MODES, fmt::arg("esc", ESC)); + + _move_back(previous_position); +} + +void StatusLine::set_status(StatusLineSection section, + const std::string_view &str) noexcept +{ + _clear_section(section); + + int32_t section_start = _get_section_start_x(section); + + const auto previous_position = _move_to_statusline(section_start); + + auto background_color = get_background_esc_seq(STATUSBAR_COLOR); + + fmt::print("{}{}", background_color, str); + fmt::print(RESET_ALL_MODES, fmt::arg("esc", ESC)); + + _move_back(previous_position); +} + +Vector2 StatusLine::_move_to_statusline(int32_t x) noexcept +{ + const auto previous_position = _cursor_controller->where(); + + const auto window_size = _window->size(); + + _cursor_controller->hide(); + + auto window_height = static_cast<Vector2::Value>(window_size.get_height()); + + _cursor_controller->move_to(Vector2({.x = x, .y = window_height}), true); + + return previous_position; +} + +void StatusLine::_move_back(Vector2 previous_position) noexcept +{ + _cursor_controller->move_to(previous_position, true); + _cursor_controller->show(); +} + +int32_t StatusLine::_get_section_start_x(StatusLineSection section) const noexcept +{ + int32_t section_start = 0; + + auto section_index = static_cast<int32_t>(section); + + while (section_index > 0) + { + section_start += static_cast<int32_t>( + _sections_lengths.at(StatusLineSection(section_index - 1))); + + section_index--; + } + + return section_start; +} + +void StatusLine::_clear_section(StatusLineSection section) noexcept +{ + auto section_start = _get_section_start_x(section); + + const auto previous_position = _move_to_statusline(section_start); + + auto background_color = get_background_esc_seq(STATUSBAR_COLOR); + + auto section_length = _sections_lengths.at(section); + + fmt::print("{}{}", background_color, std::string(section_length, ' ')); + fmt::print(RESET_ALL_MODES, fmt::arg("esc", ESC)); + + _move_back(previous_position); +} diff --git a/src/game/statusline.hpp b/src/game/statusline.hpp new file mode 100644 index 0000000..7db1e0b --- /dev/null +++ b/src/game/statusline.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "interfaces/cursor.hpp" +#include "interfaces/statusline.hpp" +#include "interfaces/window.hpp" + +#include "engine/data/vector2.hpp" + +#include <cstdint> +#include <fmt/core.h> +#include <memory> +#include <string_view> +#include <unordered_map> + +constexpr uint32_t STATUSBAR_COLOR = 0x1A1A1AU; + +class StatusLine : public IStatusLine +{ +public: + StatusLine(std::shared_ptr<ICursorController> cursor_controller, + std::shared_ptr<IWindow> window) noexcept; + + void initialize_background() noexcept override; + + void set_status(StatusLineSection section, + const std::string_view &str) noexcept override; + +private: + std::unordered_map<StatusLineSection, uint32_t> _sections_lengths; + + std::shared_ptr<ICursorController> _cursor_controller; + std::shared_ptr<IWindow> _window; + + Vector2 _move_to_statusline(int32_t x) noexcept; + + void _move_back(Vector2 previous_position) noexcept; + + int32_t _get_section_start_x(StatusLineSection section) const noexcept; + + void _clear_section(StatusLineSection section) noexcept; +}; |