Основні комбінації на основі опитування


9

Тож припустимо, що у вас є система введення, яка базується на опитуванні

void update()
{
    if( Keyboard[ 'A' ] )
        // A is down
}

Скажімо, ви хочете вміти розпізнавати комбінації клавіш довжиною від 3 до 8 (наприклад, вниз, вперед, вперед, A для hado-ken)

Як вам найкраще створити загальну систему введення комбінацій клавіш (легко модифікується / програмується) на опитуванні ?

Відповіді:


7

По суті, ви не можете . Комбінації клавіш вимагають замовлення, а замовлення вимагає подій.

Що ви можете зробити, це перетворити опитування на події, порівнюючи ключові стани кожного кадру та генеруючи пост-хок події клавіатури / клавіші з відмінностей. Це не так надійно, оскільки ви втрачаєте часові позначки та інші внутрішні кадри, які надають "рідні" системи подій, але це дозволить виявити та замовити хоча б одну клавішу на кадр.

Після того, як у вас є впорядковані події, ви можете використовувати машину з кінцевим станом чи інший інструмент, щоб зіставити їх із вашими списками переміщення та виконати правильний.


Трохи вводити в оману сказати, що не можна обійтися без подій. Технічно події - це лише спосіб викликати метод або список методів, коли виконується певна умова. У цьому сенсі потрібні події. Однак я можу застосувати слово події (неправильно) до багатьох завдань програмування, що відповідають цьому опису. Я додав відповідь, яка вирішує проблему так, як це я зазвичай роблю, і не використовує те, що більшість програмістів вважають "подіями".
Ольховський

2
Ваш код робить саме те, що я казав, без подій, але ігнорує застереження - це те, що ви втрачаєте внутрішньокадрове впорядкування. Коли ви отримуєте події, наприклад, цикл повідомлень Win32, ви отримуєте їх у порядку з більш детальністю, ніж глобул на кадр. Коли ви самі обчислюєте дельти, ви втрачаєте це. Для бойової гри, де гравці можуть вводити декілька частин комбо в один кадр, вам потрібно знати, чи не вийшли з ладу.

Справедливо. За умови, що ми опитуємось на частоті 60 Гц, я сумніваюся, що ми хочемо розрізнити між пресами, меншими за 16 м, окрім 60 ГГц, що дає опитування (якщо припустити, що наші гравці - люди).
Ольховський

Так. Кваліфіковані гравці з бойовими іграми можуть вводити команду палиці hadouken / shoryuken менше ніж на три кадри, тобто ми повинні їх відрізняти.

Тоді потрібно опитувати частіше 60 ГГц.
Ольховський

3

Один із способів - це збереження поточного та попереднього станів введення та порівняння їх кожного разу, коли ви запитуєте вхід.

Для кожної клавіші, яку можна натиснути, зберігайте об’єкт, який має часову позначку останнього разу, коли ключ перейшов із стану вниз у стан вгору.

Оновіть ці об’єкти, роблячи це під час кожного опитування:

void update(){
    some_key_has_been_pressed = false;
    foreach(key in keys){
        if(previous_input[key].Down && current_input[key].Up){
            keys[key].up_timestamp = current_time();
        }

        if(current_input[key].Down){
            keys[key].down_timestamp = current_time();
            some_key_has_been_pressed = true;
        }
    }
}

Тепер ви можете відповідати комбінаціям вмісту keys.

Майте об’єкт комбо для кожного комбо, а при кожному опитуванні виклик update () для кожного об'єднаного об'єкта.

Метод оновлення () об'єкта комбо буде узгоджуватися з комбо, перевіряючи, чи всі необхідні умови комбо виконані під час цього опитування. Тобто всі часові позначки клавіш для комбо поки що в порядку, і жодна інша клавіша, яка б порушила комбо, не була натиснута на цей кадр. Для кожної виконаної умови збільшуйте лічильник у об'єкті комбо до наступної умови для перевірки. Коли всі умови дотримані в комбо, викличте метод, який комбо повинен виконати. Якщо some_key_has_been_pressed == trueклавіша, що є наступною умовою для комбо, не була натиснута, то відновіть лічильник задоволених умов комбо до 0.

Зазначене вище є моїм кращим методом, оскільки це простий у здійсненні, простий у обслуговуванні, ефективний та високомодульний.

Однак для іншого хорошого методу ознайомтеся з зразком вхідної послідовності XNA , який записаний на C #, і логіка, ймовірно, переноситься на мову, яку ви використовуєте.


У другому if-заяві, if(current_input[key].down){чи не хочете ви також перевірити, чи ключ був у previous_inputштаті? Як написано, я думаю, що це буде постійно оновлювати утримуваний ключ down_timestamp.
webdevkit

Постійне оновлення часової позначки вниз - це призначена поведінка. Це дозволяє порівнювати позначку up_timestamp і down_timestamp будь-якої клавіші, щоб перевірити, як довго вона трималася. Якщо ви постійно тримаєте клавішу, ви не змінюєте позначку up_timestamp, тому (down_timestamp - up_timestamp) все одно надає вам тривалість, протягом якої вона трималася.
Ольховський

дякую за роз’яснення Я думав навпаки, де up_timestamp - down_timestamp - тривалість утримуваного ключа.
webdevkit

1

Створіть стек останніх ключових подій X, до кожної ключової події додайте об’єкт із ключем та часом натискання / випуску, а потім перевірте, чи відповідають останні члени стека спеціальній схемі та чи ці клавіші були натиснуті досить швидко, щоб вважати комбінацією. Нарешті видаліть найстаріший об’єкт із стека.


2
Стек, з якого можна видалити нижній об’єкт, насправді не є стеком;)
Олховський

Впорядкована купа об'єктів даних, список може бути правильним терміном.
aaaaaaaaaaaa

deque;) O (1) enq / deq ftw.
michael.bartnett

3
Впорядкована послідовність, коли об’єкти ставлять на один кінець і видаляються з іншого, найбільш правильно називають чергою .

1
Ви можете зробити буфер-дзвінок (BufferLength> = найдовша команда) і записати до нього ключі (Position = Число MOD BufferLength). Додавання / видалення не потрібно буде взагалі
Kromster
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.