aboutsummaryrefslogtreecommitdiff
path: root/src/game/game.cpp
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2022-06-02 19:51:54 +0200
committerHampusM <hampus@hampusmat.com>2022-06-13 17:57:00 +0200
commiteecf4b1e666211a13afa56f93477c55e8fd01621 (patch)
tree410510d6e058995174d5a5b0f535fb457a0c3542 /src/game/game.cpp
parent87f55120f96d0f4f80b497dc9006d89df2dda125 (diff)
feat: implement game of lifev0.1.0
Diffstat (limited to 'src/game/game.cpp')
-rw-r--r--src/game/game.cpp103
1 files changed, 89 insertions, 14 deletions
diff --git a/src/game/game.cpp b/src/game/game.cpp
index 41bafdf..55877bb 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -1,7 +1,10 @@
#include "game.hpp"
+#include "util/algorithm.hpp"
+
#include <fmt/core.h>
+#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <utility>
@@ -11,13 +14,14 @@ Game::Game(
std::shared_ptr<ICursorController> cursor_controller,
std::shared_ptr<IGenerationTracker> generation_tracker,
std::shared_ptr<IStatusManager> status_manager,
- std::shared_ptr<IUserInputObserver> user_input_observer) noexcept
+ std::shared_ptr<IUserInputObserver> user_input_observer,
+ std::shared_ptr<ICellHelper> cell_helper) noexcept
: _scene(std::move(scene)),
_cursor_controller(std::move(cursor_controller)),
_generation_tracker(std::move(generation_tracker)),
_status_manager(std::move(status_manager)),
_user_input_observer(std::move(user_input_observer)),
- _gen_update_speed_millis(1000)
+ _cell_helper(std::move(cell_helper))
{
}
@@ -31,6 +35,8 @@ void Game::on_start() noexcept
_status_manager->set_section_title(StatusLineSection::D, "Paused: ");
_status_manager->set_section_title(StatusLineSection::E, "Generation: ");
_status_manager->set_section_title(StatusLineSection::F, "Time since last frame: ");
+ _status_manager->set_section_title(StatusLineSection::G, "Living cells: ");
+ _status_manager->set_section_title(StatusLineSection::H, "Window size: ");
const auto scene_size = _scene->size();
@@ -56,6 +62,15 @@ void Game::on_start() noexcept
_status_manager->set_section_body(StatusLineSection::F, "0");
+ _status_manager->set_section_body(StatusLineSection::G, "0");
+
+ _status_manager->set_section_body(
+ StatusLineSection::H,
+ fmt::format(
+ "Width {} Height {}",
+ scene_size.get_width(),
+ scene_size.get_height()));
+
_last_update_time = std::chrono::system_clock::now();
}
@@ -64,6 +79,7 @@ void Game::on_update() noexcept
const auto pressed_key = _user_input_observer->get_currently_pressed_key();
auto cursor_has_moved = false;
+ auto is_generation_stepping = false;
switch (pressed_key)
{
@@ -91,8 +107,19 @@ void Game::on_update() noexcept
std::exit(EXIT_SUCCESS);
case 'i':
- _insert_cell(_cursor_controller->where(), 'x');
+ {
+ const auto position = _cursor_controller->where();
+ const auto matrix = _scene->get_matrix();
+
+ if (matrix->get(position) == 'x')
+ {
+ break;
+ }
+
+ _set_space(matrix, position, 'x');
+ _living_cell_positions.push_back(position);
break;
+ }
case 'p':
{
@@ -104,6 +131,10 @@ void Game::on_update() noexcept
break;
}
+ case 's':
+ is_generation_stepping = true;
+ break;
+
default:
break;
}
@@ -129,12 +160,21 @@ void Game::on_update() noexcept
StatusLineSection::F,
fmt::format("{} nanoseconds", time_since_last_update.count()));
+ _status_manager->set_section_body(
+ StatusLineSection::G,
+ fmt::format("{}", _living_cell_positions.size()));
+
+ if (_generation_tracker->get_is_paused() && !is_generation_stepping)
+ {
+ _last_update_time = time_now;
+ return;
+ }
+
const auto time_since_last_gen_update =
std::chrono::duration_cast<std::chrono::milliseconds>(
time_now - _last_gen_update_time);
- if (!_generation_tracker->get_is_paused() &&
- time_since_last_gen_update.count() > _gen_update_speed_millis)
+ if (time_since_last_gen_update.count() > GENERATION_UPDATE_SPEED_MILLIS)
{
const auto new_current_gen = _generation_tracker->get_current_generation() + 1U;
@@ -147,6 +187,36 @@ void Game::on_update() noexcept
_last_gen_update_time = time_now;
}
+ auto matrix = _scene->get_matrix();
+
+ const auto dying_cell_positions = container_filter(
+ _living_cell_positions,
+ [this](const Vector2 &cell_pos)
+ {
+ return _cell_helper->is_cell_dying(cell_pos);
+ });
+
+ auto birth_cell_positions =
+ _cell_helper->get_birth_cell_positions(_living_cell_positions);
+
+ for (const auto &dying_cell_pos : dying_cell_positions)
+ {
+ _set_space(matrix, dying_cell_pos, ' ');
+
+ const auto cell_found = container_find(_living_cell_positions, dying_cell_pos);
+
+ if (cell_found != _living_cell_positions.end())
+ {
+ _living_cell_positions.erase(cell_found);
+ }
+ }
+
+ for (const auto &birth_cell_pos : birth_cell_positions)
+ {
+ _set_space(matrix, birth_cell_pos, 'x');
+ _living_cell_positions.push_back(birth_cell_pos);
+ }
+
_last_update_time = time_now;
}
@@ -167,28 +237,33 @@ void Game::on_exit() const noexcept
void Game::_move_cursor(const Vector2 &direction) noexcept
{
- const auto new_position = _cursor_controller->where().to_direction(direction, 1);
+ const auto current_position = _cursor_controller->where();
+
+ const auto dest_position = current_position + direction;
const auto scene_size = _scene->size();
- if (scene_size.validate_coords(new_position) != CoordsValidation::VALID)
+ if (scene_size.validate_coords(dest_position) != CoordsValidation::VALID)
{
return;
}
- _cursor_controller->move_to(new_position);
+ _cursor_controller->move_to(dest_position);
}
-void Game::_insert_cell(const Vector2 &position, char cell) noexcept
+void Game::_set_space(
+ const std::shared_ptr<IMatrix<IScene::MatrixElement>> &matrix,
+ const Vector2 &position,
+ char character) noexcept
{
- std::cout.put(cell);
- std::cout.flush();
+ const auto prev_position = _cursor_controller->where();
_cursor_controller->move_to(position);
- auto matrix = _scene->get_matrix();
+ std::cout.put(character);
+ std::cout.flush();
- const auto pos_offset = Vector2({.x = 0U, .y = 1U});
+ matrix->set(position, character);
- matrix->set(position - pos_offset, cell);
+ _cursor_controller->move_to(prev_position);
}