Докуметация Cтарт Статьи Форум Лента Вход
Не официальное русскоязычное сообщество

Обработка Ввода

Опубликованно: 13.05.2017, 20:04
Последняя редакция, Andry: 02.10.2017 16:29

Пользователи взаимодействуют с вашим jME3 приложением с помощью различных устройств ввода — мышью, клавиатурой или джойстиком. Для реакции на ввод мы используем объект inputManager в SimpleApplication.

Вот как вы добавляете взаимодействие в свою игру:

  1. Для каждого действия выберите триггер(ы) (клавиши или кнопки мыши и.т.д.)
  2. Каждому действию добавьте сопоставление триггера в InputManager
  3. Создайте хотя бы один слушатель в SimpleApplication
  4. Для каждого действия зарегистрируйте его сопоставлению слушателя
  5. Реализуйте каждое действие в слушателе

Образцы кода

1. Выберите «Триггер»

Выберите одно или несколько событий «клавиатуры/мыши» для взаимодействия. Мы используем константы KeyTrigger, MouseAxisTrigger, MouseButtonTrigger, JoyAxisTrigger и JoyButtonTrigger из пакета com.jme3.input.controls.

Триггеры MouseAxis и JoyAxis идут по оси X (вправо/влево) или по оси Y (вверх/вниз). Эти триггеры поставляются с дополнительными логическими значениями для отрицательной половины оси (влево, вниз). Не забудьте написать код, который будет слушать отрицательные ли (true) и положительные (false) оси!
Триггер  Код
Кнопка мыши: Клик левой кнопкой  MouseButtonTrigger(MouseInput.BUTTON_LEFT)
Кнопка мыши: Клик правой кнопкой  MouseButtonTrigger(MouseInput.BUTTON_RIGHT)
Кнопка мыши: Клик средней кнопкой  MouseButtonTrigger(MouseInput.BUTTON_MIDDLE)
Движение мышью: Вправо  MouseAxisTrigger(MouseInput.AXIS_X, true)
Движение мышью: Влево  MouseAxisTrigger(MouseInput.AXIS_X, false)
Движение мышью: Вверх  MouseAxisTrigger(MouseInput.AXIS_Y, true)
Движение мышью: Вниз  MouseAxisTrigger(MouseInput.AXIS_Y, false)
Колесико мыши: Вверх  MouseAxisTrigger(MouseInput.AXIS_WHEEL,false)
Колесико мыши: Вниз  MouseAxisTrigger(MouseInput.AXIS_WHEEL,true)
NumPad: 1, 2, 3, …  KeyTrigger(KeyInput.KEY_NUMPAD1) …
Клавиатура: 1, 2, 3, …  KeyTrigger(KeyInput.KEY_1) …
Клавиатура: A, B, C, … KeyTrigger(KeyInput.KEY_A) …
Клавиатура: Пробел  KeyTrigger(KeyInput.KEY_SPACE)
Клавиатура: Shift  KeyTrigger(KeyInput.KEY_RSHIFT),
KeyTrigger(KeyInput.KEY_LSHIFT)
Клавиатура: F1, F2, …  KeyTrigger(KeyInput.KEY_F1) …
Клавиатура: Return, Enter  KeyTrigger(KeyInput.KEY_RETURN),
KeyTrigger(KeyInput.KEY_NUMPADENTER)
Клавиатура: PageUp, PageDown  KeyTrigger(KeyInput.KEY_PGUP),
KeyTrigger(KeyInput.KEY_PGDN)
Клавиатура: Delete, Backspace  KeyTrigger(KeyInput.KEY_BACK),
KeyTrigger(KeyInput.KEY_DELETE)
Клавиатура: Escape  KeyTrigger(KeyInput.KEY_ESCAPE)
Клавиатура: Стрелки  KeyTrigger(KeyInput.KEY_DOWN),
KeyTrigger(KeyInput.KEY_UP)
KeyTrigger(KeyInput.KEY_LEFT), KeyTrigger(KeyInput.KEY_RIGHT)
Кнопки Джойстика:   JoyButtonTrigger(0, JoyInput.AXIS_POV_X),
JoyButtonTrigger(0, JoyInput.AXIS_POV_Y) ?
Движение джойстика: Вправо  JoyAxisTrigger(0, JoyInput.AXIS_POV_X, true)
Движение джойстика: Влево  JoyAxisTrigger(0, JoyInput.AXIS_POV_X, false)
Движение джойстика: Вперед  JoyAxisTrigger(0, JoyInput.AXIS_POV_Z, true)
Движение джойстика: Назад JoyAxisTrigger(0, JoyInput.AXIS_POV_Z, false)

В вашей ID среде используйте дописывание кода, чтобы быстро находить литералы триггеров. Например, в jMonkeyEngine SDK нажмите ctrlпробел или ctrl— / после текста KeyInput.| Для получения возможности выбора нужных клавиш из списка всех клавиш.

2. Удаление сопоставлений триггерам заданные по умолчанию

inputManager.deleteMapping( SimpleApplication.INPUT_MAPPING_MEMORY );
Сопоставления заданные по умолчанию Клавиши  Описание
INPUT_MAPPING_HIDE_STATS F5  Скрывает статистику в левом нижнем углу.
INPUT_MAPPING_CAMERA_POS KEY_C  Печатает отладочные сведения о камере.
INPUT_MAPPING_MEMORY KEY_M  Печатает отладочные сведения по использованию памяти.
INPUT_MAPPING_EXIT KEY_ESCAPE  Закрывает приложение, вызывая stop();. Обычно вы не удаляете его, до тех пор пока не замените его другим более лучшим способом прекращения работы приложения.

3. Добавить пользовательские сопоставления триггерам

При инициализации приложения добавьте сопоставление для каждого триггера.

Давайте сопоставлениям осмысленные названия. Название должно отражать действие, а не кнопку/клавишу (потому что кнопки/клавиши могут меняться). Вот несколько примеров:

inputManager.addMapping("Pause Game", new KeyTrigger(KeyInput.KEY_P));
inputManager.addMapping("Rotate",     new KeyTrigger(KeyInput.KEY_SPACE));
...

Есть случаи, когда вы можете предоставить более одного триггера для одного действия. Например, некоторые пользователи предпочитают клавиши WASD для навигации, в то время как другие предпочитают клавиши со стрелками. Добавьте несколько триггеров для одного сопоставления, разделив объекты триггеры запятыми:

inputManager.addMapping("Left",  new KeyTrigger(KeyInput.KEY_A),
                                 new KeyTrigger(KeyInput.KEY_LEFT)); // A и левая стрелка
inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D),
                                 new KeyTrigger(KeyInput.KEY_RIGHT)); // D и правая стрелка
                                 ...

4. Создайте слушателей

Менеджер ввода jME3 поддерживает два типа слушателей событий для ввода: AnalogListener и ActionListener. Вы можете использовать один или оба слушателя в одном приложении. Добавьте один или оба следующих фрагмента кода в основной класс на основе SimpleApplication для активации слушателей.

Оба слушателя ввода не знают, и их не волнует, какая именно клавиша была нажата. Они знают только, какое имя сопоставления ввода было вызвано.

ActionListener

com.jme3.input.controls.ActionListener

  • Используйте для завершенного «кнопка нажата или отпущена?»,«включен или выключен?» действия.
    • Примеры: пауза/возобновление, стрельба из винтовки или револьвера, прыжок, щелчок для выбора.
  • JME предоставляет вам доступ к:
    • Название сопоставление инициируемого действия.
    • Логическое значение: нажата ли кнопка, или только что была отпущена.
    • float текущего времени на кадр как фактор времени
private ActionListener actionListener = new ActionListener() {
  public void onAction(String name, boolean keyPressed, float tpf) {
     /** TODO: тест для сопоставления имен и реализации действий */
  }
};

AnalogListener

com.jme3.input.controls.AnalogListener

  • Используйте для непрерывных и постепенных действий.
    • Примеры: Прогулка, бег, вращение, ускорение транспортного средства, стрельба, (полуавтоматический) выстрел из автоматического оружия
  • JME предоставляет вам доступ к:
    • Название сопоставление инициируемого действия.
    • Поступательное float значение нарастающее по мере того как долго нажат триггер.
    • float текущего времени на кадр как фактор времени
private AnalogListener analogListener = new AnalogListener() {
  public void onAnalog(String name, float keyPressed, float tpf) {
     /** TODO: тест для сопоставления имен и реализации действий */
  }
};

4. Регистрирование сопоставлений в слушателе

Чтобы активировать сопоставления, вы должны зарегистрировать их в Listener. Напишите свой код регистрации после блока кода, где вы добавили сопоставления в InputManager.

В следующем примере вы регистрируете сопоставление «Pause Game» в объекте actionListener, потому что пауза в игре является завершенным действием. Либо нажата либо нет.

inputManager.addListener(actionListener, new String[]{"Pause Game"});

В следующем примере вы регистрируете навигационные сопоставления с использование объекта analogListener, потому что ходьба является непрерывным действием. Игроки обычно удерживают клавишу нажатой, чтобы реализовать непрерывность, например, когда он хочет «ускоритмя» или «идти дальше».

inputManager.addListener(analogListener, new String[]{"Left", "Right"});

Как вы видите, вы можете добавить несколько слушателей в один String массив. Вы можете вызывать метод addListener() более одного раза, каждый раз с подмножеством вашего списка, если это поможет вам сохранить код аккуратным. Опять же, слушателей не заботит то, какие клавиши настроены, вы только регистрируете названия отображений триггеров.

Вы зарегистрировали действие, но оно не работает? Проверьте орфографию и регистр букв, он чувствителен к регистру!

5. Реализовать действия в Listeners

Необходимо указать действие в фрагменте кода, которое срабатывает, когда Listener говорит TODO. Обычно вы еще пишете ряд условий if/else, проверяющие все названия сопоставлений, а затем вызывая соответствующее действие.

Используйте различие между if и else if, как в этих случаях.

  • Если несколько действий могут быть запущены одновременно, протестируйте их все с помощью серии if. Например, персонаж может перемещаться вперед и влево.
  • Если некоторые действия исключают друг друга, протестируйте их с помощью else if. Остальные тесты тогда можно пропустить, и тем самым вы сэкономите несколько миллисекунд. Например, вы либо стреляете, либо подбираете что-то.

ActionListener

В самом общем случае если вы хотите, чтобы действие запускалось всего один раз, в тот момент, когда кнопка или клавиша триггера отпускаются. Например, когда игрок нажимает клавишу, чтобы открыть дверь, или нажимает, чтобы забрать предмет. Для этих случаев используйте ActionListener и тест для && !keyPressed, как показано в следующем примере.

private ActionListener actionListener = new ActionListener() {
    public void onAction(String name, boolean keyPressed, float tpf) {

      if (name.equals("Pause Game") && !keyPressed) { // тест?
        isRunning = !isRunning;                       // действие!
      }

      if ...

    }
  };

AnalogListener

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

private AnalogListener analogListener = new AnalogListener() {
    public void onAnalog(String name, float value, float tpf) {

      if (name.equals("Rotate")) {         // тест?
        player.rotate(0, value*speed, 0);  // действие!
      }

      if ...

    }
  };

Разрешить переназначение клавиш пользователям

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

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


Переведено для jmonkeyengine.ru, оригинал
Автор перевода: Andry

Добавить комментарий

jMonkeyEngine.ru © 2017. Все права сохранены.