В libGDX игре или приложении обработка событий позволяет получить более детальную и прежде всего хронологическую информацию о входных данных от пользователя. Обработка событий обеспечивает способ реализации взаимодействия с пользовательским интерфейсом, где важны конкретные последовательности ввода, например зажатие кнопки и затем отпускание означает, что пользователь нажал кнопку. Такое взаимодействие трудно реализовать с помощью опроса состояния клавиши.
Процессор ввода
Обработка событий осуществляется с помощью общего шаблона наблюдателя. Сначала мы должны реализовать интерфейс обработчик, называемый InputProcessor
:
public class MyInputProcessor implements InputProcessor { @Override public boolean keyDown (int keycode) { return false; } @Override public boolean keyUp (int keycode) { return false; } @Override public boolean keyTyped (char character) { return false; } @Override public boolean touchDown (int x, int y, int pointer, int button) { return false; } @Override public boolean touchUp (int x, int y, int pointer, int button) { return false; } @Override public boolean touchDragged (int x, int y, int pointer) { return false; } @Override public boolean touchMoved (int x, int y) { return false; } @Override public boolean scrolled (int amount) { return false; } }
Первые три метода позволяют перехватывать события клавиатуры:
- keyDown(): метод вызывается, когда была нажата клавиша. Сообщает код клавиши, который можно найти в Keys классе.
- keyUp(): метод вызывается, когда была отпущена клавиша. Сообщает код клавиши, как указано выше.
- keyTyped(): метод вызывается, когда был сгенерирован Unicode символ при вводе с клавиатуры.
keyTyped()
метод может быть использован для реализации текстовых полей и аналогичных элементов пользовательского интерфейса.
Следующие три метода сообщают о событиях мыши и сенсорного экрана:
- touchDown(): метод вызывается, когда палец коснулся экрана или была нажата кнопка мыши. Сообщает последние известные координаты, а также индекс указателя и кнопку мыши (для сенсорных экранов всегда Buttons.LEFT).
- touchUp(): метод вызывается, когда палец был убран с экрана или была отпущена кнопка мыши. Сообщает последние известные координаты, а также
индекс указателя и кнопку мыши (для сенсорных экранов всегда
Buttons.LEFT
). - touchDragged(): метод вызывается, когда палец перемещается по экрану или перемещается мышь с нажатой кнопкой. Какая была нажата кнопка – не
сообщается, так как во время движения могло быть нажато несколько кнопок. В libGDX вы можете использовать
Gdx.input.isButtonPressed()
метод для проверки определенной кнопки. - touchMoved(): метод вызывается, когда мышь перемещается по экрану без нажатой кнопки. Это событие имеет значение только для персонального
компьютера, и никогда не будет вызываться на устройствах с сенсорным экраном, где вы можете получить только
touchDragged()
событие. - scrolled(): метод вызывается, когда совершается прокрутка колеса мыши. Сообщает значение -1 или 1, в зависимости от направления вращения. Этот метод никогда не вызывается для устройств с сенсорным экраном.
Каждый из методов возвращает boolean
значение. Почему это так, мы изучим в разделе о классе InputMultiplexer
.
После реализации InputProcessor
нужно сказать об этом libGDX, чтобы фреймворк мог вызвать ее, когда придет новое событие.
MyInputProcessor inputProcessor = new MyInputProcessor(); Gdx.input.setInputProcessor(inputProcessor);
С этого момента все новые события ввода будет сообщаться MyInputProcessor экземпляру.
InputAdapter
В libGDX существует InputAdapter
класс, который реализует полностью интерфейс InputProcessor
, возвращая false в каждом методе.
Вы можете наследоваться от InputAdapter
класса и переопределить необходимые методы. Также можно использовать анонимные внутренние классы.
Gdx.input.setInputProcessor(new InputAdapter(){ public boolean touchDown(int x,int y,int pointer,int button){ // код при нажатии return true; // возвращает true, сообщая, что событие было обработано } public boolean touchUp(int x,int y,int pointer,int button){ // код при отпускании return true; // возвращает true, сообщая, что событие было обработано } });
InputMultiplexer
Иногда хочется иметь несколько InputProcessor
, например один процессор для пользовательского интерфейса, который лучше вызывать первым, а
второй процессор для событий ввода, который управляет игровым миром. Для достижения этой цели можно воспользоваться
InputMultiplexer классом libGDX фреймворка.
InputMultiplexer multiplexer = new InputMultiplexer(); multiplexer.addProcessor(new MyUiInputProcessor()); multiplexer.addProcessor(new MyGameInputProcessor()); Gdx.input.setInputProcessor(multiplexer);
Класс InputMultiplexer
будет перенаправлять новые события первому InputProcessor
. Если этот процессор вернет
false
из
вызванного метода обработки события, это указывает на то, что событие не было обработано и мультиплексор передаст событие другому процессору.
Благодаря этому механизму в libGDX, MyUiInputProcessor
может обрабатывать любые события, которые исходят от элементов управления и
передавать любые другие события в MyGameInputProcessor
.
Пример непрерывной обработки ввода
Если вы хотите перемещать в игре персонажа, используя процессор ввода, то вы заметите, что персонаж будет двигаться только тогда, когда нажата клавиша. Для
непрерывной обработки событий ввода или перемещения спрайта, вы можете добавить boolean
флаг в класс персонажа.
public class Bob { boolean leftMove; boolean rightMove; ... updateMotion() { if (leftMove) { x -= 5 * Gdx.graphics.getDeltaTime(); } if (rightMove) { x += 5 * Gdx.graphics.getDeltaTime(); } } ... public void setLeftMove(boolean t) { if(rightMove && t) rightMove = false; leftMove = t; } public void setRightMove(boolean t) { if(leftMove && t) leftMove = false; rightMove = t; }
Процессор ввода
... @Override public boolean keyDown(int keycode) { switch (keycode) { case Keys.LEFT: bob.setLeftMove(true); break; case Keys.RIGHT: bob.setRightMove(true); break; } return true; } @Override public boolean keyUp(int keycode) { switch (keycode) { case Keys.LEFT: bob.setLeftMove(false); break; case Keys.RIGHT: bob.setRightMove(false); break; } return true; }