#include "game.hpp" #include #include #include #include Game::Game( std::shared_ptr scene, std::shared_ptr cursor_controller, std::shared_ptr generation_tracker, std::shared_ptr status_manager, std::shared_ptr user_input_observer) 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) { } void Game::on_start() noexcept { _status_manager->initialize(); _status_manager->set_section_title(StatusLineSection::A, ""); _status_manager->set_section_title(StatusLineSection::B, "X: "); _status_manager->set_section_title(StatusLineSection::C, "Y: "); _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: "); const auto scene_size = _scene->size(); const auto center_position = Vector2( {.x = static_cast(scene_size.get_width()) / 2, .y = static_cast(scene_size.get_height()) / 2}); _cursor_controller->move_to(center_position); _status_manager->set_section_body( StatusLineSection::B, fmt::format("{}", center_position.get_x())); _status_manager->set_section_body( StatusLineSection::C, fmt::format("{}", center_position.get_y())); _status_manager->set_section_body( StatusLineSection::D, _generation_tracker->get_is_paused() ? "yes" : "no"); _status_manager->set_section_body(StatusLineSection::E, "0"); _status_manager->set_section_body(StatusLineSection::F, "0"); _last_update_time = std::chrono::system_clock::now(); } void Game::on_update() noexcept { if (_user_input_observer->is_key_pressed('q')) { std::exit(EXIT_SUCCESS); } if (_user_input_observer->is_key_pressed('i')) { const auto position = _cursor_controller->where(); std::cout.put('x'); std::cout.flush(); _cursor_controller->move_to(position); auto matrix = _scene->get_matrix(); const auto pos_offset = Vector2({.x = 0U, .y = 1U}); matrix->set(position - pos_offset, "#"); } auto cursor_has_moved = false; if (_user_input_observer->is_key_pressed('h')) { _move_cursor(Vector2::left()); cursor_has_moved = true; } if (_user_input_observer->is_key_pressed('j')) { _move_cursor(Vector2::down()); cursor_has_moved = true; } if (_user_input_observer->is_key_pressed('k')) { _move_cursor(Vector2::up()); cursor_has_moved = true; } if (_user_input_observer->is_key_pressed('l')) { _move_cursor(Vector2::right()); cursor_has_moved = true; } if (cursor_has_moved) { const auto current_pos = _cursor_controller->where(); _status_manager->set_section_body( StatusLineSection::B, fmt::format("{}", current_pos.get_x())); _status_manager->set_section_body( StatusLineSection::C, fmt::format("{}", current_pos.get_y())); } if (_user_input_observer->is_key_pressed('p')) { auto onoff = !_generation_tracker->get_is_paused(); _generation_tracker->set_is_paused(onoff); _status_manager->set_section_body(StatusLineSection::D, onoff ? "yes" : "no"); } const auto time_now = std::chrono::system_clock::now(); const auto time_since_last_update = time_now - _last_update_time; _status_manager->set_section_body( StatusLineSection::F, fmt::format("{} nanoseconds", time_since_last_update.count())); 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) { const auto new_current_gen = _generation_tracker->get_current_generation() + 1U; _generation_tracker->set_current_generation(new_current_gen); _status_manager->set_section_body( StatusLineSection::E, fmt::format("{}", new_current_gen)); _last_gen_update_time = time_now; } _last_update_time = time_now; } void Game::on_exit() const noexcept { for (auto row : *_scene->get_matrix()) { for (auto &col : row) { fmt::print("{}", col); } fmt::print("\n"); } std::cout.flush(); } void Game::_move_cursor(const Vector2 &direction) noexcept { const auto new_position = _cursor_controller->where().to_direction(direction, 1); const auto scene_size = _scene->size(); if (scene_size.validate_coords(new_position) != CoordsValidation::VALID) { return; } _cursor_controller->move_to(new_position); }