Опрос против событийно-ориентированного ввода

19

Я разрабатываю игру, используя опрос для метода ввода. Однако теперь, когда я углубляюсь в игровые меню и другие компоненты пользовательского интерфейса, я обнаружил, что, вероятно, хотел бы получить ввод, управляемый событиями. Возможно, даже и то и другое: использование событий, управляемых для пользовательского интерфейса, и опрос для ввода «мира». Мне любопытно, что лучший способ пойти.

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

Я определяю событие, управляемое как: события, основанные на прерываниях, когда происходит событие и запускается прерывание, и на основе события запускается блок кода.

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

РЕДАКТИРОВАТЬ

Игра основана на Java / OpenGL, поэтому будет выпущена для Windows / Mac / Linux. Возможность распространения этого на мобильные устройства невелика. Игра в стиле RTS, 3-е лицо 3D.

РЕДАКТИРОВАТЬ 2

Я до сих пор не совсем доволен тем, как я это реализовал, но я двигаюсь к тому, чтобы перехватывать события в моем пользовательском интерфейсе, и если они не обрабатываются ни одним из моих компонентов пользовательского интерфейса, я передаю событие на «Мир» для комплектации / выбора. Что-то вроде:

@Override  
private boolean handleEvent(Event event) {  
    if(hud.handleEvent(event)) {  
        return true;  
    }  
    return WORLD.handleEvent(event);  
}

Таким образом, я не получаю щелчки, просачивающиеся через пользовательский интерфейс, чтобы выбрать объекты за кнопками, а что нет.

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

Я ценю все ответы, извините, я мог выбрать только один!

MichaelHouse
источник
6
Я не уверен в Java, но в целом вы всегда должны опрашивать ввод. Затем вы можете публиковать события, когда все меняется, но это все еще основано на системе опроса.
Джеймс
На мой взгляд, наиболее важным моментом является разработка цикла событий, свободного от любой другой загрузки, кроме сбора входных данных. Позвольте мне объяснить: операционная система выполнит прерывание, управляемое вводом, и обработает его в глобальном «потоке ввода», затем этот поток ОС перенаправит сообщения в находящееся в фокусе приложение и запишет intel в свою очередь сообщений. Очередь сообщений должна быть опрошена PeekMessage или GetMessage. Самый быстрый способ получить это - использовать GetMessage и позволить планировщику разбудить вас, тогда вы можете очень точно отметить время сообщения.
v.oddou

Ответы:

17

Это зависит от требований вашей игры и оборудования. Большинство игр обычно заинтересованы в изменении состояния ввода, то есть пользователь нажимает клавишу огня, и его оружие начинает стрелять, пользователь отпускает клавишу огня, и его оружие прекращает стрелять, пользователь нажимает клавишу движения и начинает движение, отпускает клавишу движения и прекращает движение и т. д., поэтому управляемая событиями система ввода в этих случаях наиболее целесообразна, поскольку информация уже находится в подходящем формате. Кроме того, на платформе Windows вы уже получаете события для изменений состояния клавиатуры и мыши, поэтому зачастую это преобразование 1: 1 из низкоуровневых входных событий в высокоуровневые игровые события. При опросе вам часто приходится создавать такие события вручную, сравнивая состояние между текущим и последним кадром. По сути, "какие кнопки сейчас нажимаются?"

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

Скайлер Йорк
источник
Спасибо, я включил дополнительную информацию о платформе и цели игры.
MichaelHouse
1
Обратите внимание, что GetAsyncKeyStateэто простой способ использовать опрос на Win32.
Маке
Сумасшедший, я задал вопрос в комментариях Нейта Бросса, с которыми вы здесь сталкиваетесь, так что, думаю, я его уточню. Все ли ПК предлагают аппаратное прерывание 1: 1 для связи событий клавиатуры ОС, и какие платформы ограничены низкоуровневым опросом?
michael.bartnett
@Macke: иногда антивирус сообщает о программах, использующих этот API, потому что они могут получать нажатия клавиш от всей глобальной системы, что позволяет вести злонамеренный кейлоггинг. Самая удивительная статья об этом во всем Интернете (я знаю) это: securelist.com/analysis/publications/36358/…
v.oddou
7

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

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

mouseInput = GetMouse();
kbInput = GetKeyboard();


// refactor this out to its own method if it makes sense
if menuState == Showing
    if mouseInput.LeftButton == State.Pressed
        LeftButton(mouseInput.X, mouseInput.Y)

// rest of game input code processing

void LeftButton(int x, int y)
{
    // left button event handler
}

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

Nate
источник
1
Мне любопытно, как природа получает информацию от устройств. Являются ли события клавиатуры, отправляемые ОС, результатом опроса на уровне драйвера устройства? Или событие клавиатуры соответствует прерыванию? Или есть прерывания, но ОС буферизует их и отправляет их, когда считает нужным?
michael.bartnett
Я не уверен в том, как это работает на этом уровне, но это самое основное, некоторые программы работают в цикле и проверяют состояние клавиатуры и сравнивают ее с предыдущим состоянием, если оно изменилось, изменение всплывает.
Nate
5

Здесь есть две разные проблемы:

  1. Как вы читаете пользовательский ввод с ОС / аппаратного обеспечения?

  2. Как вы обрабатываете пользовательский ввод в вашем движке?

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

Для обработки есть несколько разных вариантов:

  • Для управления движением игрока (и аналогичных схем) опрос может быть проще, поскольку вам нужно пересчитывать скорость каждого кадра. Весьма вероятно, что ваш внутренний цикл будет основан на опросе:

    то есть что-то вроде speed += 1 if button.down else -1; clamp(speed, 0, 42);

  • Для дискретных событий (стрельба, игра в паузу, телепорт на другую сторону планеты) обработка событий предпочтительнее, иначе ваш код будет завален maybeLaunchMissile(key_state);звонками, и это просто ... плохо, хорошо. ;)

Надеюсь, это поможет.

Маке
источник