В 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;
}