Аргумент, что вам "нужен цикл, потому что в противном случае то, что вызывает прослушиватель событий", не выдерживает критики. По общему признанию в любой основной ОС у вас действительно есть такой цикл, и слушатели событий работают таким образом, но вполне возможно создать систему, управляемую прерываниями, которая работает без каких-либо циклов.
Но вы все равно не захотите структурировать игру таким образом.
То, что делает цикл наиболее привлекательным решением, заключается в том, что ваш цикл становится тем, что в программировании в реальном времени называется «циклическим исполнителем». Идея состоит в том, что вы можете сделать относительные скорости выполнения различных действий системы детерминированными по отношению друг к другу. Общая скорость цикла может контролироваться таймером, и этот таймер может в конечном итоге быть прерыванием, но в современных ОС вы, скорее всего, увидите это прерывание в виде кода, который ожидает семафор (или некоторый другой механизм синхронизации), как часть вашего "основного цикла".
Так зачем вам детерминированное поведение? Рассмотрим относительные скорости обработки входных данных вашего пользователя и искусственных интеллектов. Если вы поместите все в систему, основанную исключительно на событиях, нет гарантии, что ИИ не получат больше процессорного времени, чем ваш пользователь, или наоборот, если у вас нет некоторого контроля над приоритетами потоков, и даже тогда вы склонны испытывать трудности с поддержанием согласованности сроков.
Однако поставьте все в цикл, и вы гарантируете, что временные линии вашего ИИ будут работать в фиксированных отношениях с временем вашего пользователя. Это достигается с помощью вызова из вашего цикла, чтобы дать AI временной интервал, в котором нужно решить, что делать, вызов ваших пользовательских процедур ввода, опросить устройства ввода, чтобы выяснить, как ваш пользователь хочет себя вести, и вызовите, чтобы сделать ваш рендеринг.
При таком цикле вы должны следить за тем, чтобы не тратить больше времени на обработку каждого прохода, чем на самом деле в реальном времени. Если вы пытаетесь выполнить цикл с частотой 100 Гц, лучше, чтобы обработка всего цикла была завершена менее чем за 10 мсек, в противном случае ваша система будет работать с перебоями. В программировании в реальном времени это называется превышением ваших временных рамок. Хорошая система позволит вам отслеживать, насколько вы близки к обгону, а затем вы сможете уменьшить нагрузку на обработку, как считаете нужным.