#include "engine.hpp" #include #include #include #include #include #include #include #include #include "interfaces/component.hpp" #include "interfaces/cursor.hpp" #include "interfaces/input.hpp" #include "interfaces/scene.hpp" #include "util/function_impl.hpp" CLIGameEngine::CLIGameEngine( IGameFactory game_factory, IComponentRendererFactory component_renderer_factory, std::shared_ptr user_input_observer, std::shared_ptr cursor_controller, std::shared_ptr scene) noexcept : _game_factory(std::move(game_factory)), _component_renderer_factory(std::move(component_renderer_factory)), _user_input_observer(std::move(user_input_observer)), _cursor_controller(std::move(cursor_controller)), _scene(std::move(scene)) { } void CLIGameEngine::start() noexcept { auto component_renderer = _component_renderer_factory(_cursor_controller); _scene->enter(); _cursor_controller->set_bounds(_scene->size()); auto game = _game_factory(_scene, _cursor_controller, _user_input_observer); try { game->on_start(); } catch (const std::exception &error) { _scene->leave(); fmt::print("Error: {}\n", error.what()); return; } std::atexit(normalize_lambda( [this, &game]() { _scene->leave(); game->on_exit(); })); auto listen_input_thread = std::thread(normalize_lambda( [this]() { _user_input_observer->listen(); })); auto last_update_time = std::chrono::system_clock::now(); const auto get_millis_since_update = [&last_update_time]() { return std::chrono::duration_cast( std::chrono::system_clock::now() - last_update_time); }; while (true) { const auto time_since_last_update = get_millis_since_update(); if (time_since_last_update.count() < MIN_TIME_SINCE_LAST_UPDATE_MILLIS) { while (get_millis_since_update().count() < MIN_TIME_SINCE_LAST_UPDATE_MILLIS) { } } game->on_update(); for (auto [component, position] : _scene->get_components()) { if (component->get_need_render()) { component_renderer->render(component, position); component->set_need_render(false); } } last_update_time = std::chrono::system_clock::now(); } }