Примечание: я должен опрашивать, а не делать обратные вызовы из-за ограничений API (SFML). Я также извиняюсь за отсутствие «приличного» названия.
Я думаю, у меня есть два вопроса здесь; как зарегистрировать вход, который я получаю, и что с ним делать.
Обработка ввода
Я говорю после того, как вы зарегистрировали тот факт, что, например, была нажата клавиша «А», и как это сделать.
Я видел массив всей клавиатуры, что-то вроде:
bool keyboard[256]; //And each input loop check the state of every key on the keyboard
Но это кажется неэффективным. Например, вы не только связываете клавишу «А» с «игроком, двигающимся влево», но и проверяет каждую клавишу 30–60 раз в секунду.
Затем я попробовал другую систему, которая просто искала нужные ключи.
std::map< unsigned char, Key> keyMap; //Key stores the keycode, and whether it's been pressed. Then, I declare a load of const unsigned char called 'Quit' or 'PlayerLeft'.
input->BindKey(Keys::PlayerLeft, KeyCode::A); //so now you can check if PlayerLeft, rather than if A.
Однако проблема в том, что теперь я не могу ввести имя, например, без необходимости связывать каждый ключ.
Затем у меня есть вторая проблема, которую я не могу придумать для хорошего решения:
Отправка ввода
Теперь я знаю, что была нажата клавиша A или что playerLeft - это правда. Но как мне идти отсюда?
Я думал о простой проверке.
if(input->IsKeyDown(Key::PlayerLeft) { player.MoveLeft(); }
Это сильно связывает ввод с сущностями, и я нахожу это довольно грязным. Я бы предпочел, чтобы игрок обрабатывал свое собственное движение, когда оно обновляется. Я думал, что какая-то система событий могла бы работать, но я не знаю, как с этим справиться. (Я слышал, что сигналы и слоты были хороши для такой работы, но, по-видимому, они очень медленные, и я не вижу, как они подходят).
Благодарю.
источник
Я думаю, что обсуждение ОП сводит воедино кучу вещей, и что проблему можно существенно упростить, немного ее разобрав.
Мое предложение:
Держите ваш массив состояний ключей. Разве нет вызова API для получения всего состояния клавиатуры одновременно? (Большая часть моей работы над консолями, и даже в Windows для подключенного контроллера вы получаете сразу все состояние контроллера.) Ваши состояния клавиш представляют собой «жесткую» карту клавиш клавиатуры. Непереведенный вариант лучше, но, тем не менее, его проще всего получить из API.
Затем сохраните несколько параллельных массивов, которые указывают, пошел ли ключ вверх по этому кадру, другой, указывающий, что он пошел вниз, и третий, чтобы просто указать, что клавиша «нажата». Может быть, включить таймер, чтобы вы могли отслеживать, как долго ключ находится в его текущем состоянии.
Затем создайте метод для сопоставления ключей с действиями. Вы захотите сделать это пару раз. Один раз для пользовательского интерфейса (и позаботьтесь о том, чтобы запросить сопоставления Windows, потому что вы не можете предположить, что скан-код, когда вы нажимаете «А», будет давать А на компьютере пользователя). Еще для каждого внутриигрового «режима». Это сопоставления ключевых кодов с действиями. Вы можете сделать это несколькими способами, один из них - сохранить перечисление, используемое принимающей системой, другой - указатель на функцию, указывающий функцию, вызываемую при изменении состояния. Может быть, даже гибрид из двух, в зависимости от ваших целей и потребностей. С этими "режимами" вы можете помещать их в стек режимов контроллера и вставлять их с флагами, которые позволяют игнорируемому вводу продолжать работу в стеке или что-то еще.
Наконец, обработайте эти ключевые действия как-нибудь. Для движения вы можете сделать что-то хитрое, переведите «W» вниз, чтобы обозначить «двигаться вперед», но это не обязательно должно быть двоичным решением; у вас может быть «W is down» означает «увеличить скорость на X до максимума Y», а «W up» означает «уменьшить скорость на Z, пока она не достигнет нуля». В общем, вы хотите, чтобы ваш «интерфейс управления контроллером в игровых системах» был довольно узким; сделать все ключевые переводы в одном месте, а затем использовать результаты этого везде. Это в отличие от прямой проверки, чтобы увидеть, нажимается ли пробел где-нибудь случайно в коде, потому что, если он находится в каком-то случайном месте, он, вероятно, попадет в случайное время, когда вы этого не хотите, и вы просто не не хочу иметь дело с этим ...
Я действительно не люблю проектировать шаблоны и думаю, что компоненты приносят больше затрат на разработку, чем хороших, поэтому я не упомянул ни то, ни другое. Шаблоны появятся, если им предназначено, как и компоненты, но если вы захотите сделать что-либо с самого начала, это только осложнит вашу жизнь.
источник
В SFML у вас есть клавиши в том порядке, в котором они были нажаты с типом события KeyPressed. Вы обрабатываете каждый ключ некоторое время (getNextEvent ()).
Поэтому, если нажатая клавиша находится на вашей карте Key-> Action, запустите соответствующее действие, а если нет, перешлите его на любой виджет / материал, который может понадобиться.
Что касается вашего второго вопроса, я бы порекомендовал вам сохранить его таким, потому что он облегчает настройку игрового процесса. Если вы используете сигналы или что-то подобное, вам нужно будет сделать слот для «RunKeyDown», а другой - для «JumpKeySlot». Но что произойдет, если в вашей игре специальное действие будет выполнено при нажатии обеих клавиш?
Если вы хотите декоррелировать входные данные и сущности, вы можете сделать свой вход State (RunKey = true, FireKey = false, ...) и отправить его игроку, как вы отправляете любое другое событие своим AI.
источник
Правильное решение часто является комбинацией двух методов, которые вы обсуждаете:
Для функциональности игрового процесса с предопределенным набором ключей опрос каждого кадра полностью уместен, и вам следует опросить только те ключи, которые действительно связаны с чем-то. Это на самом деле аналогично тому, как вы запрашиваете ввод контроллера в консольной игре, это будет полностью опрос, особенно когда речь идет об устройствах аналогового ввода. Во время общего игрового процесса вы, вероятно, хотите игнорировать события нажатия клавиш и просто использовать опрос.
Когда дело доходит до ввода ввода для таких вещей, как имена, вы должны переключить игру в другой режим обработки ввода. Например, как только появится подсказка «введите ваше имя», вы можете изменить то, что делает вводимый код. Он может либо прослушивать события нажатия клавиш через некоторый интерфейс обратного вызова, либо вы можете начать опрос для каждой клавиши, если это необходимо. Оказывается, что, как правило, во время ввода событий вы все равно не заботитесь о производительности, поэтому опрос не будет таким уж плохим.
Таким образом, вы хотите использовать выборочный опрос для ввода в игровой процесс и обработку событий для ввода ввода имени (или весь опрос с клавиатуры, если обработка событий недоступна).
источник
Мне очень нравится ответ dash-tom-bang, он действительно выделяет некоторые аспекты, которые вы должны учитывать при проектировании системы ввода.
Я хотел бы добавить небольшой учебник, на который я наткнулся, который идет в том же направлении (включая входные контексты, 3 слоя, ...):
http://www.gamedev.net/blog/355/entry-2250186-designing-a-robust-input-handling-system-for-games/
источник