Обработка многократных нажатий клавиш
Модератор: Модераторы
- shade
- энтузиаст
- Сообщения: 879
- Зарегистрирован: 21.02.2006 19:15:48
- Откуда: http://shamangrad.net/
- Контактная информация:
Обработка многократных нажатий клавиш
В движке для реализации перемещений с помощью клавиш нужна поддержка многократных нажатий.
Например, клавиша W - движение в перед
клавиша D - движение вправо
клавиша A - движение влево
игрок нажимает и удерживает W, при этом он по перемено нажимает A и D, - и герой в игре двигается змейкой.
Как реализовать такое в Lazarus? Может можно как-то опрашивать клавиатуру? Под Windows это можно сделать с помощью GetKeyState/GetAsyncKeyState), может есть кроссплатформный аналог?
Или прийдется на OnKeyDown/OnKeyUp/OnTimer заполнять массив нажатий - как сейчас и реализовал - но частота таймера слишком маленькая... (вообще в данном движке таймер и не нужен, по крайней мере пока - все реакции по событиям)
Например, клавиша W - движение в перед
клавиша D - движение вправо
клавиша A - движение влево
игрок нажимает и удерживает W, при этом он по перемено нажимает A и D, - и герой в игре двигается змейкой.
Как реализовать такое в Lazarus? Может можно как-то опрашивать клавиатуру? Под Windows это можно сделать с помощью GetKeyState/GetAsyncKeyState), может есть кроссплатформный аналог?
Или прийдется на OnKeyDown/OnKeyUp/OnTimer заполнять массив нажатий - как сейчас и реализовал - но частота таймера слишком маленькая... (вообще в данном движке таймер и не нужен, по крайней мере пока - все реакции по событиям)
shade писал(а):В движке для реализации перемещений с помощью клавиш нужна поддержка многократных нажатий.
Например, клавиша W - движение в перед
клавиша D - движение вправо
клавиша A - движение влево
игрок нажимает и удерживает W, при этом он по перемено нажимает A и D, - и герой в игре двигается змейкой.
Как реализовать такое в Lazarus? Может можно как-то опрашивать клавиатуру? Под Windows это можно сделать с помощью GetKeyState/GetAsyncKeyState), может есть кроссплатформный аналог?
Или прийдется на OnKeyDown/OnKeyUp/OnTimer заполнять массив нажатий - как сейчас и реализовал - но частота таймера слишком маленькая... (вообще в данном движке таймер и не нужен, по крайней мере пока - все реакции по событиям)
попробуй так!
создаешь буфер нажатых клавиш, вешаешь обработчик на кейап и кейдаун, при нажатии заносишь в буфер полученный код и увеличиваешь счетчик на единицу, при отпускании клавиши удаляешь код с буфера и уменьшаешь счетчик. Должно сработать.
- shade
- энтузиаст
- Сообщения: 879
- Зарегистрирован: 21.02.2006 19:15:48
- Откуда: http://shamangrad.net/
- Контактная информация:
SAK писал(а):А зачем таймер? OnKeyDown устанавливает флаг нажатия, OnKeyUp - снимает его. Или я что-то не понимаю.
Нажимаем и держим W - идут OnKeyDown с W
нажимаем и держим A - идут OnKeyDown с A
отпускаем A - более ни каких OnKeyDown не будет даже не смотря на то, что W мы не отпускали
haword писал(а):попробуй так!
Я так и сделал. Не понял только за чем счетчик?
Я вот и говорю, что частоты таймера мне не хватает - движение рывками
shade писал(а):SAK писал(а):А зачем таймер? OnKeyDown устанавливает флаг нажатия, OnKeyUp - снимает его. Или я что-то не понимаю.
Нажимаем и держим W - идут OnKeyDown с W
нажимаем и держим A - идут OnKeyDown с A
отпускаем A - более ни каких OnKeyDown не будет даже не смотря на то, что W мы не отпускалиhaword писал(а):попробуй так!
Я так и сделал. Не понял только за чем счетчик?
Я вот и говорю, что частоты таймера мне не хватает - движение рывками
Я пробывал, после отпускания любой клавиши идет ОнКейАп с кодом! Для этого и счетчик чтобы знать количество одновременно нажатых клавишь. И странно таймер под виндой кажись до 1 милисекунды может срабатывать, этого чтоли не хватает времени?
-
SAK
- постоялец
- Сообщения: 158
- Зарегистрирован: 17.02.2006 23:45:14
- Откуда: Тим
- Контактная информация:
Всё же не понимаю.
Делаем флаги: flagA, flagW. При OnKeyDown с A устанавливаем flagA:=true; OnKeyDown с W - flagW:=true; Для OnKeyUp соответственно каждой клавише сбрасываем флаги в false. Теперь не имеет значение идут события OnKeyDown после первого нажатия или нет, анализируем только соответствующий флаг который будет сброшен только после отпускания соответствующей ему клавиши. Событие OnKeyDown фиксируется только для нажатия клавиши автоповторы отбрасываются. Зачем надо знать количество одновременно нажатых клавиш?
PS. Или частота автоповтора задаёт скорость игры? Но для этого всё же таймер лучше.
Делаем флаги: flagA, flagW. При OnKeyDown с A устанавливаем flagA:=true; OnKeyDown с W - flagW:=true; Для OnKeyUp соответственно каждой клавише сбрасываем флаги в false. Теперь не имеет значение идут события OnKeyDown после первого нажатия или нет, анализируем только соответствующий флаг который будет сброшен только после отпускания соответствующей ему клавиши. Событие OnKeyDown фиксируется только для нажатия клавиши автоповторы отбрасываются. Зачем надо знать количество одновременно нажатых клавиш?
PS. Или частота автоповтора задаёт скорость игры? Но для этого всё же таймер лучше.
- shade
- энтузиаст
- Сообщения: 879
- Зарегистрирован: 21.02.2006 19:15:48
- Откуда: http://shamangrad.net/
- Контактная информация:
Yogrik писал(а):А таймер имеется в виду TTimer???
Именно TTimer... Есть альтернативы?
SAK писал(а):PS. Или частота автоповтора задаёт скорость игры? Но для этого всё же таймер лучше.
Движок не игровой, поэтому понятия скорости нет. И таймера пока не нужно, только вот ради обработки нажатий и сделал таймер.
SAK писал(а):Событие OnKeyDown фиксируется только для нажатия клавиши автоповторы отбрасываются.
В случае однократных нажатий использовал автоповторы и все работало нормально. А при использования многократных нажатий, автоповтор работает только для последней нажатой клавиши и если она отпускается, то автоповторы прекращаются.
haword писал(а):Я пробывал, после отпускания любой клавиши идет ОнКейАп с кодом! Для этого и счетчик чтобы знать количество одновременно нажатых клавишь.
ОнКейАпом никаких проблем небыло и нет.
Мне не нужно знать сколько клавиш нажато, мне нужно знать только какие. Для этого я использую TKeyState = set of byte;
при OnKeyDown: KeyState := KeyState + [Key]
при OnKeyUp: KeyState := KeyState - [Key]
В таймере просто проверка:
if VK_W in KeyState then shift_camera_forward(step_len);
и т.п.
haword писал(а):И странно таймер под виндой кажись до 1 милисекунды может срабатывать, этого чтоли не хватает времени?
Задать кончено можно до 1мс, но не факт что события будут идти с такой скростью.
На новых тачках может быть, а вот на мой с пустым таймером где-то до 30мс можно отсчитывать, точно не помню раньше замерял, а тут еще нужно сцену рендерить.
В общем все работает как я и писал в первом сообщении. Я просто думал, что можно как-то обойтись без таймера..
Впрочем ладно, многократные нажатия работают.
А дискретизация/сглаживание движений это другая тема..
PS: Просто интересно (но в данной ситуации бесполезно), можно ли в Lazarus определить нажата некоторая клавиша или нет - без обработки OnKeyDown/OnKeyUp? и не используя платформно зависимые юниты типа windows.
SAK писал(а):Всё же не понимаю.
Делаем флаги: flagA, flagW. При OnKeyDown с A устанавливаем flagA:=true; OnKeyDown с W - flagW:=true; Для OnKeyUp соответственно каждой клавише сбрасываем флаги в false. Теперь не имеет значение идут события OnKeyDown после первого нажатия или нет, анализируем только соответствующий флаг который будет сброшен только после отпускания соответствующей ему клавиши. Событие OnKeyDown фиксируется только для нажатия клавиши автоповторы отбрасываются. Зачем надо знать количество одновременно нажатых клавиш?
А если одновременно три клавиши нажмешь? или четыре? или все 10? Мое решение было бы буфер с нажатыми клавишами. Счетчик можно использовать к примеру при нажатии более 4 клавиш ни на что не реагировать. Хотя можно и считать количество цифр в буфере. Кому как удобнее.
