aboutsummaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2022-03-23 19:41:31 +0100
committerHampusM <hampus@hampusmat.com>2022-06-13 17:56:57 +0200
commit486ca3846b46dc229e5807968578809766ec1991 (patch)
tree65a4b7a746d6305666af06f8a1975c76244085a7 /src/game
parentb8e86ce397dc07320c02f6a5f592c7c6a4421c86 (diff)
feat: implement generations & multithreading
Diffstat (limited to 'src/game')
-rw-r--r--src/game/cursor_listener.cpp14
-rw-r--r--src/game/cursor_listener.hpp19
-rw-r--r--src/game/game.cpp26
-rw-r--r--src/game/game.hpp21
-rw-r--r--src/game/generation_tracker.cpp18
-rw-r--r--src/game/generation_tracker.hpp22
-rw-r--r--src/game/status_updater.cpp25
-rw-r--r--src/game/status_updater.hpp24
-rw-r--r--src/game/statusline.cpp102
-rw-r--r--src/game/statusline.hpp41
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;
+};