/** * \brief The main function. * * The main loop is executed here. */ void MainLoop::run() { // Main loop. uint32_t last_frame_date = System::get_real_time(); uint32_t lag = 0; // Lose time of the simulation to catch up. uint32_t time_dropped = 0; // Time that won't be caught up. // The main loop basically repeats // check_input(), update(), draw() and sleep(). // Each call to update() makes the simulated time advance one fixed step. while (!is_exiting()) { // Measure the time of the last iteration. uint32_t now = System::get_real_time() - time_dropped; uint32_t last_frame_duration = now - last_frame_date; last_frame_date = now; lag += last_frame_duration; // At this point, lag represents how much late the simulated time with // compared to the real time. if (lag >= 200) { // Huge lag: don't try to catch up. // Maybe we have just made a one-time heavy operation like loading a // big file, or the process was just unsuspended. // Let's fake the real time instead. time_dropped += lag - System::timestep; lag = System::timestep; last_frame_date = System::get_real_time() - time_dropped; } // 1. Detect and handle input events. check_input(); // 2. Update the world once, or several times (skipping some draws) // to catch up if the system is slow. int num_updates = 0; while (lag >= System::timestep && num_updates < 10 // To draw sometimes anyway on very slow systems. && !is_exiting()) { update(); lag -= System::timestep; ++num_updates; } // 3. Redraw the screen. if (num_updates > 0) { draw(); } // 4. Sleep if we have time, to save CPU and GPU cycles. last_frame_duration = (System::get_real_time() - time_dropped) - last_frame_date; if (last_frame_duration < System::timestep) { System::sleep(System::timestep - last_frame_duration); } } }
/** * \brief The main function. * * The main loop is executed here. */ void MainLoop::run() { // Main loop. uint32_t last_frame_date = System::get_real_time(); uint32_t lag = 0; // Lose time of the simulation. // The main loop basically repeats // check_input(), update(), draw() and sleep(). // Each call to update() makes the simulated time advance one fixed step. while (!is_exiting()) { // Measure the time of the last iteration without the check_input() phase. // Some check_input() calls are much slower than other, for example when // they involve loading a map. However, these long check_input() calls do // not mean that the system is slow and that we should skip drawings, // unlike long updates and long drawings. // That is is why to compute the lag, we ignore the time spent in // check_input(). uint32_t current_frame_date = System::get_real_time(); uint32_t last_frame_duration = current_frame_date - last_frame_date; // 1. Detect and handle input events. check_input(); last_frame_date = System::get_real_time(); lag += last_frame_duration; // At this point, lag represents how much late the simulated time with // compared to the real time. // 2. Update the world once, or several times (skipping some draws) // if the system is slow. int num_updates = 0; while (lag >= System::timestep && num_updates < 10 // To draw sometimes anyway on very slow systems. && !is_exiting()) { update(); lag -= System::timestep; ++num_updates; } // 3. Redraw the screen. draw(); // 4. Sleep if we have time, to save CPU cycles. if (System::get_real_time() - last_frame_date < System::timestep) { System::sleep(1); } } }
/** * \brief Enables accepting standard input lines as Lua commands. */ void MainLoop::initialize_lua_console() { // Watch stdin in a separate thread. stdin_thread = std::thread([this]() { std::string line; while (!is_exiting()) { if (std::getline(std::cin, line)) { while (!line.empty() && std::isspace(line.at(line.size() - 1))) { line.erase(line.size() - 1); } if (!line.empty()) { push_lua_command(line); } } } }); stdin_thread.detach(); }
/** * @brief The main function. * * The main loop is executed here. * The input events are forwarded to the current screen. * The current screen is redrawn when necessary. */ void Solarus::main_loop() { // main loop InputEvent *event; uint32_t now; uint32_t next_frame_date = System::now(); uint32_t frame_interval = 25; // time interval between to displays int delay; bool just_displayed = false; // to detect when the FPS number needs to be decreased while (!is_exiting()) { // handle the input events event = InputEvent::get_event(); if (event != NULL) { notify_event(*event); delete event; } // update the current screen update(); // go to another screen? if (current_screen->is_screen_finished()) { Screen *next_screen = current_screen->get_next_screen(); delete current_screen; if (next_screen != NULL) { current_screen = next_screen; } else { current_screen = new LanguageScreen(*this); } } else { now = System::now(); delay = next_frame_date - now; // delay is the time remaining before the next display if (delay <= 0) { // it's time to display // see if the FPS number is too high if (just_displayed && frame_interval <= 30) { frame_interval += 5; // display the screen less often //std::cout << "\rFPS: " << (1000 / frame_interval) << std::flush; } next_frame_date = now + frame_interval; just_displayed = true; display(); } else { just_displayed = false; // if we have time, let's sleep to avoid using all the processor System::sleep(1); if (delay >= 15) { // if we have much time, increase the FPS number frame_interval--; //std::cout << "\rFPS: " << (1000 / frame_interval) << std::flush; } } } } }