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

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

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

Ответ 1

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

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

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

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

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

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

Ответ 2

Слушатель событий также зависит от какого-то цикла вызова, видите ли вы это или нет. Кто еще будет звонить слушателю?

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

Ответ 3

Неверно, что для всех видов игр требуется специальный игровой цикл.

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

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

Ответ 4

Игровой цикл (очень упрощенный):

initialise
do
     input
     update
     render
loop
clean up

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

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

Если вы должны были обновляться только при вводе пользователя, игра будет реагировать только тогда, когда пользователь вводит ввод. Другие игровые компоненты, такие как игровые объекты A.I, не будут реагировать самостоятельно. Таким образом, петля является самым простым и лучшим способом обновления игры.

Ответ 5

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

Ответ 6

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

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

На простом уровне вы можете концептуализировать CPU, чтобы иметь несколько таймеров;

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

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

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

void int_handler1();
//...
int main() 
{ 
  //install interrupt handlers
  //configure settings
  while(1);
}

Ответ 7

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

Ответ 8

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

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

Ответ 9

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

Ответ 10

Две причины -

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

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

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

Ответ 11

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

schedule(updateEvent, 33ms)

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

против

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

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