Подтвердить что ты не робот

SDL_PollEvent против SDL_WaitEvent

Итак, я читал эту статью, которая содержит "Советы и рекомендации для многопоточного программирования в SDL" - https://vilimpoc.org/research/portmonitorg/sdl-tips-and-tricks.html

Это говорит о том, что SDL_PollEvent неэффективен, поскольку он может вызвать чрезмерное использование ЦП и поэтому рекомендует использовать SDL_WaitEvent.

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

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

Правильно ли я думаю, что я должен продолжать использовать SDL_PollEvent для общего игрового программирования?

4b9b3361

Ответ 1

Если ваша игра только обновляет/переписывает ввод пользователя, вы можете использовать SDL_WaitEvent. Однако в большинстве игр анимация/физика продолжается, даже когда пользователь не вводит пользователя. Поэтому я думаю, что SDL_PollEvent лучше всего подходит для большинства игр.

Один случай, когда SDL_WaitEvent может быть полезен, - это если вы используете его в одном потоке, а ваша анимация/логика - в другом потоке. Таким образом, даже если SDL_WaitEvent ждет долгое время, ваша игра продолжит рисование/обновление. (EDIT: Это может не работать. См. Комментарий Хенрика ниже)

Что касается SDL_PollEvent, использующего 100% CPU в качестве указанной статьи, вы можете уменьшить это, добавив спать в свой цикл, когда обнаружите, что ваша игра работает больше, чем требуемые кадры в секунду.

Ответ 2

Если вам не нужна точность подкадра в вашем входе, и ваша игра постоянно оживляет, тогда подходит SDL_PollEvent.

Точность подкадра может быть важна, например. игры, в которых игроку могут потребоваться очень небольшие приращения в движении - быстрое нажатие и отпускание клавиши имеет непредсказуемое поведение, если вы используете классический ленивый метод keydown для обозначения "velocity = 1" и keyup для обозначения "velocity = 0", а затем вы только обновить позицию за один кадр. Если ваш кран происходит с перекрытием с рендерингом кадра, вы получаете один кадр продолжительности движения, если он не дает никакого движения, где то, что вы действительно хотите, - это количество движения меньше длины кадра на основе временных меток на котором произошли события.

К сожалению, события SDL не включают в себя фактические временные метки событий из операционной системы, только временную метку вызова PumpEvents, а WaitEvent эффективно опросает с интервалом 10 мс, поэтому даже с WaitEvent, работающим в отдельном потоке, Получится 10 мс (вы могли бы приблизиться к меньшему, сказав, что если вы получите keydown и keyup в одном и том же цикле опроса, тогда это ~ 5 мс).

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

К сожалению, SDL_PumpEvents должен запускаться в потоке, который инициализировал видеоподсистему (за https://wiki.libsdl.org/SDL_PumpEvents), поэтому вся идея запуска ваш входной цикл в другом потоке, чтобы получить синхронизацию подкадра, ограничена каркасом SDL.

В заключение, для приложений SDL с анимацией нет причин использовать ничего, кроме SDL_PollEvents. Лучшее, что вы можете сделать для входной точности sub-framerate: если у вас есть время для записи между кадрами, у вас есть возможность быть точным в течение этого времени, но тогда вы получите странные окна рендеринга каждый кадр, где ваш вход теряет точность, поэтому вы оказываетесь в другом виде несоответствия.

Ответ 3

В общем, вы должны использовать SDL_WaitEvent, а не SDL_PollEvent, чтобы освободить CPU в операционной системе для обработки других задач, например обработки ввода данных. Это проявит к вам пользователей как вялую реакцию на ввод пользователя, так как это может вызвать задержку между тем, когда они вводят команду, и когда ваше приложение обрабатывает событие. Вместо этого вместо использования SDL_WaitEvent ОС может быстрее отправлять события в приложение, что улучшает воспринимаемую производительность.

В качестве побочного преимущества пользователи в системах с батарейным питанием, такие как ноутбуки и портативные устройства, должны немного снизить потребление батареи, так как у ОС есть возможность уменьшить общее использование ЦП, так как ваша игра не использует его в 100% случаев - он будет использовать его только тогда, когда происходит событие.

Ответ 4

Вы могли бы на самом деле инициализировать SDL и окно в основном потоке, а затем создать еще 2 потока для обновлений (просто обновляет игровые состояния и переменные с течением времени) и рендеринга (соответственно отображает поверхности). Затем, после всего этого, используйте SDL_WaitEvent в главном потоке для управления SDL_Events. Таким образом, вы можете убедиться, что событие управляется в том же потоке, который вызвал sdl_init.

Я долго использовал этот метод, чтобы мои игры работали в Windows и Linux и смог успешно запустить 3 потока одновременно, как упоминалось выше.

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

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