From eecf4b1e666211a13afa56f93477c55e8fd01621 Mon Sep 17 00:00:00 2001 From: HampusM Date: Thu, 2 Jun 2022 19:51:54 +0200 Subject: feat: implement game of life --- src/game/game.cpp | 103 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 89 insertions(+), 14 deletions(-) (limited to 'src/game/game.cpp') 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 +#include #include #include #include @@ -11,13 +14,14 @@ Game::Game( std::shared_ptr cursor_controller, std::shared_ptr generation_tracker, std::shared_ptr status_manager, - std::shared_ptr user_input_observer) noexcept + std::shared_ptr user_input_observer, + std::shared_ptr 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( 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> &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); } -- cgit v1.2.3-18-g5258