Почему “основной” игровой цикл необходим для разработки игры?

Я нахожу, что большая часть разработки игр требует основного игрового цикла, но я не знаю, почему это необходимо. Разве мы не могли реализовать слушателя события и ответить на каждое пользовательское действие? Анимации (и т.д.). мог затем играться, когда событие имеет место.

Какова цель основного игрового цикла?

47
задан Miles Rout 23 June 2014 в 11:33
поделиться

11 ответов

Аргумент, что вам «нужен цикл, потому что в противном случае то, что вызывает прослушиватель событий», не выдерживает критики. По общему признанию, в любой основной ОС такой цикл действительно есть, и слушатели событий работают таким образом, но вполне возможно создать систему, управляемую прерываниями, которая работает без каких-либо циклов.

Но вы все равно не хотели бы строить игру таким образом.

Что делает цикл наиболее привлекательным решением, так это то, что ваш цикл становится тем, что в программировании в реальном времени называется «циклическим исполнителем». Идея состоит в том, что вы можете сделать относительную скорость выполнения различных действий системы детерминированной по отношению друг к другу. Общая скорость цикла может контролироваться таймером, и этот таймер в конечном итоге может быть прерыванием, но в современных ОС вы, вероятно, увидите свидетельство этого прерывания в виде кода, который ожидает семафор (или какой-либо другой механизм синхронизации) как часть вашего «основного цикла».

Так зачем вам детерминированное поведение? Учитывайте относительную скорость обработки входных данных вашего пользователя и злодеев ИИ. Если вы поместите все в систему, основанную исключительно на событиях, нет гарантии, что ИИ не получат больше процессорного времени, чем ваш пользователь, или наоборот, если только у вас нет некоторого контроля над приоритетами потоков, и даже тогда вы склонны к трудностям в соблюдении сроков.

Поместите все в цикл, и вы гарантируете, что ваши временные рамки ИИ будут продолжаться в фиксированной зависимости от времени вашего пользователя.Это достигается путем вызова из вашего цикла, чтобы дать ИИ временной отрезок, в котором он может решить, что делать, вызова ваших подпрограмм пользовательского ввода, чтобы опросить устройства ввода, чтобы узнать, как ваш пользователь хочет себя вести, и позвать, чтобы сделать рендеринг.

С таким циклом вы должны следить за тем, чтобы на обработку каждого прохода у вас не уходило больше времени, чем на самом деле происходит в реальном времени. Если вы пытаетесь зациклить свой цикл на частоте 100 Гц, всю обработку вашего цикла лучше завершить менее чем за 10 мсек, иначе ваша система будет рывками. В программировании в реальном времени это называется превышением временных рамок. Хорошая система позволит вам контролировать, насколько вы близки к перерасходу, и затем вы сможете снизить нагрузку на обработку, как вы сочтете нужным.

80
ответ дан 26 November 2019 в 19:22
поделиться

Две причины -

Даже системам, управляемым событиями, обычно нужен какой-то цикл, который считывает события из какой-либо очереди и отправляет их в обработчик, так что вы все равно получите цикл событий в окнах, например, в любом случае, и его можно было бы расширить.

Для анимации вам нужно будет обрабатывать какой-то вид даже для каждого кадра анимации. Вы, конечно, могли бы сделать это с помощью таймера или какого-либо события бездействия, но вы, вероятно, в конечном итоге создадите их в каком-то цикле, так что просто проще использовать цикл напрямую.

Я видел системы, которые обрабатывают все это с помощью событий, у них есть приемник кадров, который прослушивает событие, отправляемое в начале каждого кадра. У них все еще есть крошечный игровой цикл внутри, но он делает немного больше, чем обрабатывает события оконной системы и создает события кадра,

1
ответ дан 26 November 2019 в 19:22
поделиться

Природа игр такова, что они, как правило, моделируют и реагируют не только на внешние события, но и на внутренние процессы. Вы можете представить эти внутренние процессы повторяющимися событиями вместо опроса, но они практически эквивалентны:

schedule(updateEvent, 33ms)

function updateEvent:
    for monster in game:
        monster.update()
    render()

vs:

while 1:
    for monster in game:
        monster.update()
    wait(33ms)
    render()

Интересно, что pyglet реализует метод, основанный на событиях, вместо более традиционного цикла. И хотя в большинстве случаев это работает хорошо, иногда это вызывает проблемы с производительностью или непредсказуемое поведение, вызванное разрешением часов, vsync и т. Д. Цикл более предсказуем и проще для понимания (если вы не имеете опыта исключительно веб-программирования, возможно ).

1
ответ дан 26 November 2019 в 19:22
поделиться

Прослушиватель событий также зависит от некоторого цикла вызова, независимо от того, видите вы его или нет. Кто еще будет вызывать слушателя?

Создание явного игрового цикла дает вам полный контроль над тем, что происходит, поэтому вы не будете зависеть от того, что какой-нибудь инструментарий / библиотека обработки событий делает в своем цикле событий.

16
ответ дан 26 November 2019 в 19:22
поделиться

Это неправда, что все игры требуют выделенного главного цикла игры.

Экшн-игры нуждаются в таком цикле из-за частого обновления объектов и точности игрового ввода.

С другой стороны, я реализовал игру minesweeper и использовал window
сообщения для уведомлений.

6
ответ дан 26 November 2019 в 19:22
поделиться

Это потому, что текущие операционные системы не полностью основаны на событиях. Несмотря на то, что вещи часто представляются как события, вам все равно придется создать цикл, в котором вы ждете следующего события и обрабатываете его бесконечно (например, цикл событий Windows). Сигналы Unix, вероятно, наиболее близки к событиям на уровне ОС, но они недостаточно эффективны для подобных вещей.

4
ответ дан 26 November 2019 в 19:22
поделиться

На практике, как указывали другие люди, цикл необходим.

Однако ваша идея теоретически верна. Вам не нужен цикл. Вам нужны операции на основе событий.

На простом уровне можно представить ЦП, имеющий несколько таймеров;

  • один срабатывает по нарастающему фронту 60 Гц и вызывает блиттинг-код.
  • Другой может работать на частоте 60 кГц и обрабатывать последние обновления объектов игрового мира в блиттерном буфере.
  • Другой может работать на частоте 10 кГц и получать данные от пользователя. (довольно высокое разрешение, смеется)
  • Еще одна может быть игра «сердцебиение» и тики на 60 МГц; Искусственный интеллект и физика могут работать в мгновение ока.

Конечно, эти таймеры можно настроить.

Фактически, то, что могло бы происходить, было бы (несколько опущено) следующим образом:

void int_handler1();
//...
int main() 
{ 
  //install interrupt handlers
  //configure settings
  while(1);
}
4
ответ дан 26 November 2019 в 19:22
поделиться

Главный цикл вызывает слушателя событий. Если вам повезло, и у вас есть операционная система или оконный менеджер, управляемый событиями, то цикл событий находится там. В противном случае, вы пишете главный цикл для посредничества в "несоответствии импеданса" между интерфейсами системных вызовов, которые основаны на вводе/выводе, poll или select, и традиционным приложением, управляемым событиями.

P.S. Поскольку вы пометили свой вопрос функциональным программированием, вам стоит ознакомиться с Функционально-реактивным программированием, которое делает большую работу по соединению высокоуровневых абстракций с низкоуровневыми, основанными на событиях реализациями.

2
ответ дан 26 November 2019 в 19:22
поделиться

Любая программа, которая может просто сидеть там бесконечно долго и реагировать на ввод пользователя, нуждается в каком-то цикле. В противном случае программа просто дойдет до конца и выйдет.

2
ответ дан 26 November 2019 в 19:22
поделиться

Игра должна работать в режиме реального времени , поэтому лучше всего работает, если она постоянно работает на одном процессоре / ядре. Управляемое событиями приложение обычно передает ЦП другому потоку, если в очереди нет события. Может потребоваться значительное ожидание, прежде чем ЦП вернется к вашему процессу. В игре это означало бы короткие срывы и нервную анимацию.

2
ответ дан 26 November 2019 в 19:22
поделиться

Цикл игры (очень упрощенно выглядит следующим образом)

initialise
do
     input
     update
     render
loop
clean up

Это будет происходить каждый кадр, в котором проводится игра. Таким образом, для игр со скоростью 60 кадров в секунду вышеуказанное выполняется шестьдесят раз в секунду.

Это означает, что игра работает плавно, игра остается синхронизированной и обновления / розыгрыши за цикл происходят достаточно часто. Анимация - это просто уловка глаза: объекты перемещаются между локациями, но при достаточно быстром воспроизведении кажется, что они перемещаются между этими локациями.

Если бы вы обновляли только ввод данных пользователем, игра реагировала бы только тогда, когда пользователь вводил данные. Другие игровые компоненты, такие как игровые объекты с искусственным интеллектом, не будут реагировать сами по себе. Таким образом, цикл - это самый простой и лучший способ обновления игры.

7
ответ дан 26 November 2019 в 19:22
поделиться