Ответ 1
В тех случаях, когда функции update_game() и display_game() выполняются за меньшее время, чем один интервал кадра в 60FP, цикл пытается обеспечить, чтобы следующий кадр не обрабатывался до тех пор, пока этот интервал не достигнут, спящий (блокирующий поток) с избыточным временем кадра. Похоже, он пытается обеспечить, чтобы частота кадров была ограничена до 60FPS и не выше.
Процессор не "покидает цикл", а поток, в котором работает ваш цикл, блокируется (предотвращается от продолжения выполнения вашего кода) до тех пор, пока время ожидания не закончится. Затем он продолжается до следующего кадра. В многопоточном игровом движке, спящий поток основного игрового цикла, как это дает процессорное время для выполнения кода в других потоках, которые могут управлять физикой, AI, микшированием звука и т.д., В зависимости от настройки.
Почему GetTickCount() вызывается до начала цикла? Мы знаем из комментария в вашем коде, что GetTickCount() возвращает миллисекунды с момента загрузки системы.
Так что скажем, что система запускалась в течение 30 секунд (30 000 мс) при запуске вашей программы, и скажем, что мы не вызывали GetTickCount() перед входом в цикл, но вместо этого инициализируется next_game_tick на 0.
Мы делаем обновления и набираем вызовы (например, они берут 6 мс), а затем:
next_game_tick += SKIP_TICKS; // next_game_tick is now 16
sleep_time = next_game_tick - GetTickCount();
// GetTickCount() returns 30000!
// So sleep_time is now 16 - 30000 = -29984 !!!
Поскольку мы (разумно) спать только когда sleep_time положителен, игровой цикл будет работать как можно быстрее (потенциально быстрее, чем 60FPS), который не является тем, что вы хотите.