Обработка многократных нажатий клавиш

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Обработка многократных нажатий клавиш

Сообщение shade » 13.06.2007 20:00:04

В движке для реализации перемещений с помощью клавиш нужна поддержка многократных нажатий.
Например, клавиша W - движение в перед
клавиша D - движение вправо
клавиша A - движение влево
игрок нажимает и удерживает W, при этом он по перемено нажимает A и D, - и герой в игре двигается змейкой.

Как реализовать такое в Lazarus? Может можно как-то опрашивать клавиатуру? Под Windows это можно сделать с помощью GetKeyState/GetAsyncKeyState), может есть кроссплатформный аналог?

Или прийдется на OnKeyDown/OnKeyUp/OnTimer заполнять массив нажатий - как сейчас и реализовал - но частота таймера слишком маленькая... (вообще в данном движке таймер и не нужен, по крайней мере пока - все реакции по событиям)
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Сообщение SAK » 13.06.2007 22:42:07

А зачем таймер? OnKeyDown устанавливает флаг нажатия, OnKeyUp - снимает его. Или я что-то не понимаю.
SAK
постоялец
 
Сообщения: 158
Зарегистрирован: 18.02.2006 00:45:14
Откуда: Тим

Re: Обработка многократных нажатий клавиш

Сообщение haword » 14.06.2007 09:13:49

shade писал(а):В движке для реализации перемещений с помощью клавиш нужна поддержка многократных нажатий.
Например, клавиша W - движение в перед
клавиша D - движение вправо
клавиша A - движение влево
игрок нажимает и удерживает W, при этом он по перемено нажимает A и D, - и герой в игре двигается змейкой.

Как реализовать такое в Lazarus? Может можно как-то опрашивать клавиатуру? Под Windows это можно сделать с помощью GetKeyState/GetAsyncKeyState), может есть кроссплатформный аналог?

Или прийдется на OnKeyDown/OnKeyUp/OnTimer заполнять массив нажатий - как сейчас и реализовал - но частота таймера слишком маленькая... (вообще в данном движке таймер и не нужен, по крайней мере пока - все реакции по событиям)

попробуй так!
создаешь буфер нажатых клавиш, вешаешь обработчик на кейап и кейдаун, при нажатии заносишь в буфер полученный код и увеличиваешь счетчик на единицу, при отпускании клавиши удаляешь код с буфера и уменьшаешь счетчик. Должно сработать.
haword
постоялец
 
Сообщения: 301
Зарегистрирован: 02.03.2006 11:34:40

Сообщение shade » 14.06.2007 12:11:04

SAK писал(а):А зачем таймер? OnKeyDown устанавливает флаг нажатия, OnKeyUp - снимает его. Или я что-то не понимаю.

Нажимаем и держим W - идут OnKeyDown с W
нажимаем и держим A - идут OnKeyDown с A
отпускаем A - более ни каких OnKeyDown не будет даже не смотря на то, что W мы не отпускали

haword писал(а):попробуй так!

Я так и сделал. Не понял только за чем счетчик?
Я вот и говорю, что частоты таймера мне не хватает - движение рывками
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Сообщение Yogrik » 14.06.2007 12:20:09

А таймер имеется в виду TTimer???
Если да, то может попробывать реализовать "таймер" через поток...
Ну там типо: потоку задаются какие кнопки зажаты, а он перерисовывает то что нужно
Тогда задержки-то и не будет, но может появится мерцание, хотя и с ним можно бороться не перерисовывая лишний раз...
Yogrik
постоялец
 
Сообщения: 116
Зарегистрирован: 23.03.2006 00:41:48

Сообщение haword » 14.06.2007 13:15:35

shade писал(а):
SAK писал(а):А зачем таймер? OnKeyDown устанавливает флаг нажатия, OnKeyUp - снимает его. Или я что-то не понимаю.

Нажимаем и держим W - идут OnKeyDown с W
нажимаем и держим A - идут OnKeyDown с A
отпускаем A - более ни каких OnKeyDown не будет даже не смотря на то, что W мы не отпускали

haword писал(а):попробуй так!

Я так и сделал. Не понял только за чем счетчик?
Я вот и говорю, что частоты таймера мне не хватает - движение рывками

Я пробывал, после отпускания любой клавиши идет ОнКейАп с кодом! Для этого и счетчик чтобы знать количество одновременно нажатых клавишь. И странно таймер под виндой кажись до 1 милисекунды может срабатывать, этого чтоли не хватает времени?
haword
постоялец
 
Сообщения: 301
Зарегистрирован: 02.03.2006 11:34:40

Сообщение SAK » 14.06.2007 14:22:09

Всё же не понимаю.
Делаем флаги: flagA, flagW. При OnKeyDown с A устанавливаем flagA:=true; OnKeyDown с W - flagW:=true; Для OnKeyUp соответственно каждой клавише сбрасываем флаги в false. Теперь не имеет значение идут события OnKeyDown после первого нажатия или нет, анализируем только соответствующий флаг который будет сброшен только после отпускания соответствующей ему клавиши. Событие OnKeyDown фиксируется только для нажатия клавиши автоповторы отбрасываются. Зачем надо знать количество одновременно нажатых клавиш?

PS. Или частота автоповтора задаёт скорость игры? Но для этого всё же таймер лучше.
SAK
постоялец
 
Сообщения: 158
Зарегистрирован: 18.02.2006 00:45:14
Откуда: Тим

Сообщение shade » 14.06.2007 15:02:21

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.
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Сообщение Yogrik » 14.06.2007 16:28:40

shade писал(а):Именно TTimer... Есть альтернативы?

Альтернатив нет, но есть TIdleTime......;)
Yogrik
постоялец
 
Сообщения: 116
Зарегистрирован: 23.03.2006 00:41:48

Сообщение haword » 14.06.2007 16:39:43

SAK писал(а):Всё же не понимаю.
Делаем флаги: flagA, flagW. При OnKeyDown с A устанавливаем flagA:=true; OnKeyDown с W - flagW:=true; Для OnKeyUp соответственно каждой клавише сбрасываем флаги в false. Теперь не имеет значение идут события OnKeyDown после первого нажатия или нет, анализируем только соответствующий флаг который будет сброшен только после отпускания соответствующей ему клавиши. Событие OnKeyDown фиксируется только для нажатия клавиши автоповторы отбрасываются. Зачем надо знать количество одновременно нажатых клавиш?

А если одновременно три клавиши нажмешь? или четыре? или все 10? Мое решение было бы буфер с нажатыми клавишами. Счетчик можно использовать к примеру при нажатии более 4 клавиш ни на что не реагировать. Хотя можно и считать количество цифр в буфере. Кому как удобнее.
haword
постоялец
 
Сообщения: 301
Зарегистрирован: 02.03.2006 11:34:40

Сообщение haword » 14.06.2007 16:40:38

если кейап и кейдаун отрабатывают то и таймер не зачем
haword
постоялец
 
Сообщения: 301
Зарегистрирован: 02.03.2006 11:34:40


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 10

Рейтинг@Mail.ru