No nível do sistema, o Android informa códigos de evento de entrada de controles de jogos como códigos de tecla e valores de eixo do Android. No seu jogo, você pode receber esses códigos e valores e convertê-los em ações específicas.
Quando os jogadores se conectam fisicamente ou fazem o pareamento sem fio de um controle de jogo com
dispositivos Android, o sistema detecta automaticamente o controle
como um dispositivo de entrada e começa a relatar os eventos de entrada. Seu jogo pode receber
esses eventos de entrada implementando os seguintes métodos de callback no Activity
ativo
ou no View
focado. Implemente
os callbacks para Activity
ou
View
, mas não para ambos:
- De
Activity
:dispatchGenericMotionEvent(android.view. MotionEvent)
Chamado para processar eventos de movimento genéricos, por exemplo, movimentos do joystick.
dispatchKeyEvent(android.view.KeyEvent)
Chamado para processar eventos de tecla, como pressionar ou soltar um gamepad ou botão direcional.
- De
View
:onGenericMotionEvent(android.view.MotionEvent)
Chamado para processar eventos de movimento genéricos, por exemplo, movimentos do joystick.
onKeyDown(int, android.view.KeyEvent)
Chamado para processar o pressionamento de uma tecla física, como um gamepad ou botão direcional.
onKeyUp(int, android.view.KeyEvent)
Chamado para processar a liberação de uma tecla física, como um gamepad ou botão direcional.
A abordagem recomendada é capturar os eventos do objeto View
específico com que o usuário interage.
Inspecione os seguintes objetos fornecidos pelos callbacks para ver informações sobre o tipo de evento de entrada recebido:
KeyEvent
- Um objeto que descreve eventos
do botão direcional e do gamepad. Os eventos de tecla são acompanhados por um
código de chave que indica o botão específico acionado, como
DPAD_DOWN
ouBUTTON_A
. É possível extrair o código da tecla chamandogetKeyCode()
ou em callbacks de eventos de tecla, comoonKeyDown()
. MotionEvent
- Um objeto que descreve a entrada do joystick e de movimentos
do gatilho ombro. Os eventos de movimento são acompanhados por um código de ação e um conjunto de
valores de eixo. O código de ação especifica a mudança de estado ocorrida,
como a movimentação de um joystick. Os valores do eixo descrevem a posição e outras
propriedades de movimento de um controle físico específico, como
AXIS_X
ouAXIS_RTRIGGER
. Você pode acessar o código de ação chamandogetAction()
, e o valor do eixo chamandogetAxisValue()
.
Esta lição se concentra em como você pode processar a entrada dos tipos mais comuns de
controles físicos (botões de gamepad, botões direcionais e
joysticks) em uma tela de jogo implementando os métodos de callback
View
mencionados acima e os objetos de processamento
KeyEvent
e MotionEvent
.
Verificar se um controle de jogo está conectado
Ao relatar eventos de entrada, o Android não distingue
eventos que vieram de um dispositivo de controle que não seja de jogo e eventos que vieram
de um controle de jogo. Por exemplo, uma ação de tela sensível ao toque gera um
evento AXIS_X
que representa a coordenada
X da superfície sensível ao toque, mas um joystick gera um evento
AXIS_X
que representa a posição X do joystick. Se
o jogo se importa com o processamento da entrada do controle, primeiro confira
se o evento de entrada vem de um tipo de origem relevante.
Para verificar se um dispositivo de entrada conectado é um controle de jogo, chame
getSources()
para receber um campo de bits combinado de
tipos de origem de entrada com suporte no dispositivo. Em seguida, você pode testar se
os campos a seguir estão definidos:
- Um tipo de origem de
SOURCE_GAMEPAD
indica que o dispositivo de entrada tem botões de gamepad (por exemplo,BUTTON_A
). Esse tipo de origem não indica estritamente se o controle de jogo tem botões D-pad, embora a maioria deles tenha controles direcionais. - Um tipo de origem
SOURCE_DPAD
indica que o dispositivo de entrada tem botões direcionais (por exemplo,DPAD_UP
). - Um tipo de origem de
SOURCE_JOYSTICK
indica que o dispositivo de entrada tem controles analógicos (por exemplo, um joystick que registra movimentos ao longo deAXIS_X
eAXIS_Y
).
O snippet de código a seguir mostra um método auxiliar que permite verificar se os dispositivos de entrada conectados são controles de jogos. Em caso afirmativo, o método recupera os IDs de dispositivo dos controles de jogos. Em seguida, você pode associar cada ID de dispositivo a um jogador e processar as ações do jogo para cada jogador conectado separadamente. Para saber mais sobre o suporte a vários controles de jogos conectados simultaneamente no mesmo dispositivo Android, consulte Suporte a vários controles de jogo.
Kotlin
fun getGameControllerIds(): List<Int> { val gameControllerDeviceIds = mutableListOf<Int>() val deviceIds = InputDevice.getDeviceIds() deviceIds.forEach { deviceId -> InputDevice.getDevice(deviceId).apply { // Verify that the device has gamepad buttons, control sticks, or both. if (sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD || sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK) { // This device is a game controller. Store its device ID. gameControllerDeviceIds .takeIf { !it.contains(deviceId) } ?.add(deviceId) } } } return gameControllerDeviceIds }
Java
public ArrayList<Integer> getGameControllerIds() { ArrayList<Integer> gameControllerDeviceIds = new ArrayList<Integer>(); int[] deviceIds = InputDevice.getDeviceIds(); for (int deviceId : deviceIds) { InputDevice dev = InputDevice.getDevice(deviceId); int sources = dev.getSources(); // Verify that the device has gamepad buttons, control sticks, or both. if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) || ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK)) { // This device is a game controller. Store its device ID. if (!gameControllerDeviceIds.contains(deviceId)) { gameControllerDeviceIds.add(deviceId); } } } return gameControllerDeviceIds; }
Além disso, convém verificar os recursos de entrada individuais com suporte de um controle de jogo conectado. Isso pode ser útil, por exemplo, se você quiser que o jogo use apenas entradas do conjunto de controles físicos que ele entende.
Para detectar se um código de tecla ou de eixo específico tem suporte de um controle de jogo conectado, use estas técnicas:
- No Android 4.4 (API de nível 19) ou versões mais recentes, é possível determinar se um código de tecla tem
suporte a um controle de jogo conectado chamando
hasKeys(int...)
. - No Android 3.1 (API de nível 12) ou versões mais recentes, é possível encontrar todos os eixos disponíveis
compatíveis com um controle de jogo conectado chamando primeiro
getMotionRanges()
. Em seguida, em cada objetoInputDevice.MotionRange
retornado, chamegetAxis()
para receber o ID do eixo.
Processar o pressionamento do botão do gamepad
A Figura 1 mostra como o Android mapeia códigos de teclas e valores de eixo para os controles físicos da maioria dos controles de jogos.
![](https://developer.android.com/static/images/training/game-controller-profiles.png?authuser=5&hl=pt)
Figura 1. Perfil de um controle de jogo genérico.
As frases de destaque na figura referem-se ao seguinte:
Códigos de tecla comuns gerados pelo pressionamento do botão do gamepad incluem
BUTTON_A
,
BUTTON_B
,
BUTTON_SELECT
e BUTTON_START
. Alguns controles
de jogos também acionam o código de tecla DPAD_CENTER
quando o centro da barra cruzada do botão direcional é pressionado. Seu
jogo pode inspecionar o código de tecla chamando getKeyCode()
ou em callbacks de eventos de teclas, como
onKeyDown()
,
e, se ele representar um evento relevante para o jogo, processá-lo como uma
ação de jogo. A Tabela 1 lista as ações recomendadas para os botões de gamepad
mais comuns.
Tabela 1. Ações de jogo recomendadas para botões do gamepad.
Ação do jogo | Código da tecla do botão |
---|---|
Iniciar jogo no menu principal ou pausar/retomar durante o jogo | BUTTON_START * |
Exibir menu | BUTTON_SELECT *
e KEYCODE_MENU * |
Igual ao comportamento de navegação Voltar do Android descrito no guia de design Navegação. | KEYCODE_BACK |
Voltar para um item anterior em um menu | BUTTON_B |
Confirmar a seleção ou executar a ação principal do jogo | BUTTON_A e
DPAD_CENTER |
* Seu jogo não pode depender da presença dos botões "Iniciar", "Selecionar" ou "Menu".
Dica : considere fornecer uma tela de configuração no jogo para permitir que os usuários personalizem os próprios mapeamentos de controles para ações.
O snippet abaixo mostra como você pode substituir
onKeyDown()
para
associar os pressionamentos dos botões BUTTON_A
e
DPAD_CENTER
a uma ação do jogo.
Kotlin
class GameView(...) : View(...) { ... override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { var handled = false if (event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD) { if (event.repeatCount == 0) { when (keyCode) { // Handle gamepad and D-pad button presses to navigate the ship ... else -> { keyCode.takeIf { isFireKey(it) }?.run { // Update the ship object to fire lasers ... handled = true } } } } if (handled) { return true } } return super.onKeyDown(keyCode, event) } // Here we treat Button_A and DPAD_CENTER as the primary action // keys for the game. private fun isFireKey(keyCode: Int): Boolean = keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_BUTTON_A }
Java
public class GameView extends View { ... @Override public boolean onKeyDown(int keyCode, KeyEvent event) { boolean handled = false; if ((event.getSource() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) { if (event.getRepeatCount() == 0) { switch (keyCode) { // Handle gamepad and D-pad button presses to // navigate the ship ... default: if (isFireKey(keyCode)) { // Update the ship object to fire lasers ... handled = true; } break; } } if (handled) { return true; } } return super.onKeyDown(keyCode, event); } private static boolean isFireKey(int keyCode) { // Here we treat Button_A and DPAD_CENTER as the primary action // keys for the game. return keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_BUTTON_A; } }
Observação : no Android 4.2 (API
de nível 17) e versões anteriores, o sistema trata
BUTTON_A
como a chave
Voltar do Android por padrão. Se o app oferecer suporte a essas versões
do Android, trate
BUTTON_A
como a ação principal do
jogo. Para determinar a versão atual do SDK
do Android no dispositivo, consulte o
valor de Build.VERSION.SDK_INT
.
Processar entradas pelo botão direcional
O botão direcional de quatro direções (D-pad) é um controle físico comum em muitos controles
de jogos. O Android informa pressionamentos para CIMA e para BAIXO como
eventos AXIS_HAT_Y
com um intervalo de
-1,0 (para cima) a 1,0 (para baixo) e pressionamentos para ESQUERDA ou DIREITA como
eventos AXIS_HAT_X
com um intervalo de -1,0
(esquerda) a 1,0 (direita).
Alguns controles informam o pressionamento do botão direcional com um código de tecla. Se o jogo se importar com pressionamentos do botão direcional, trate os eventos do botão do chapéu e os códigos do botão direcional como os mesmos eventos de entrada, conforme recomendado na Tabela 2.
Tabela 2. Ações de jogo padrão recomendadas para códigos de botão direcional e valores do eixo do chapéu.
Ação do jogo | Código do botão direcional | Código do botão do ângulo de visão |
---|---|---|
Mover para cima | KEYCODE_DPAD_UP |
AXIS_HAT_Y (para valores de 0 a -1,0) |
Mover para baixo | KEYCODE_DPAD_DOWN |
AXIS_HAT_Y (para valores de 0 a 1,0) |
Mover para a esquerda | KEYCODE_DPAD_LEFT |
AXIS_HAT_X (para valores de 0 a -1,0) |
Mover para a direita | KEYCODE_DPAD_RIGHT |
AXIS_HAT_X (para valores de 0 a 1,0) |
O snippet de código abaixo mostra uma classe auxiliar que permite verificar os valores do eixo do chapéu e do código de tecla de um evento de entrada para determinar a direção do botão direcional.
Kotlin
class Dpad { private var directionPressed = -1 // initialized to -1 fun getDirectionPressed(event: InputEvent): Int { if (!isDpadDevice(event)) { return -1 } // If the input event is a MotionEvent, check its hat axis values. (event as? MotionEvent)?.apply { // Use the hat axis value to find the D-pad direction val xaxis: Float = event.getAxisValue(MotionEvent.AXIS_HAT_X) val yaxis: Float = event.getAxisValue(MotionEvent.AXIS_HAT_Y) directionPressed = when { // Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad // LEFT and RIGHT direction accordingly. xaxis.compareTo(-1.0f) == 0 -> Dpad.LEFT xaxis.compareTo(1.0f) == 0 -> Dpad.RIGHT // Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad // UP and DOWN direction accordingly. yaxis.compareTo(-1.0f) == 0 -> Dpad.UP yaxis.compareTo(1.0f) == 0 -> Dpad.DOWN else -> directionPressed } } // If the input event is a KeyEvent, check its key code. (event as? KeyEvent)?.apply { // Use the key code to find the D-pad direction. directionPressed = when(event.keyCode) { KeyEvent.KEYCODE_DPAD_LEFT -> Dpad.LEFT KeyEvent.KEYCODE_DPAD_RIGHT -> Dpad.RIGHT KeyEvent.KEYCODE_DPAD_UP -> Dpad.UP KeyEvent.KEYCODE_DPAD_DOWN -> Dpad.DOWN KeyEvent.KEYCODE_DPAD_CENTER -> Dpad.CENTER else -> directionPressed } } return directionPressed } companion object { internal const val UP = 0 internal const val LEFT = 1 internal const val RIGHT = 2 internal const val DOWN = 3 internal const val CENTER = 4 fun isDpadDevice(event: InputEvent): Boolean = // Check that input comes from a device with directional pads. event.source and InputDevice.SOURCE_DPAD != InputDevice.SOURCE_DPAD } }
Java
public class Dpad { final static int UP = 0; final static int LEFT = 1; final static int RIGHT = 2; final static int DOWN = 3; final static int CENTER = 4; int directionPressed = -1; // initialized to -1 public int getDirectionPressed(InputEvent event) { if (!isDpadDevice(event)) { return -1; } // If the input event is a MotionEvent, check its hat axis values. if (event instanceof MotionEvent) { // Use the hat axis value to find the D-pad direction MotionEvent motionEvent = (MotionEvent) event; float xaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_X); float yaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_Y); // Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad // LEFT and RIGHT direction accordingly. if (Float.compare(xaxis, -1.0f) == 0) { directionPressed = Dpad.LEFT; } else if (Float.compare(xaxis, 1.0f) == 0) { directionPressed = Dpad.RIGHT; } // Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad // UP and DOWN direction accordingly. else if (Float.compare(yaxis, -1.0f) == 0) { directionPressed = Dpad.UP; } else if (Float.compare(yaxis, 1.0f) == 0) { directionPressed = Dpad.DOWN; } } // If the input event is a KeyEvent, check its key code. else if (event instanceof KeyEvent) { // Use the key code to find the D-pad direction. KeyEvent keyEvent = (KeyEvent) event; if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) { directionPressed = Dpad.LEFT; } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT) { directionPressed = Dpad.RIGHT; } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) { directionPressed = Dpad.UP; } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) { directionPressed = Dpad.DOWN; } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER) { directionPressed = Dpad.CENTER; } } return directionPressed; } public static boolean isDpadDevice(InputEvent event) { // Check that input comes from a device with directional pads. if ((event.getSource() & InputDevice.SOURCE_DPAD) != InputDevice.SOURCE_DPAD) { return true; } else { return false; } } }
Você pode usar essa classe auxiliar no jogo sempre que quiser processar
a entrada do botão direcional, por exemplo, nos
callbacks
onGenericMotionEvent()
ou
onKeyDown()
.
Por exemplo:
Kotlin
private val dpad = Dpad() ... override fun onGenericMotionEvent(event: MotionEvent): Boolean { if (Dpad.isDpadDevice(event)) { when (dpad.getDirectionPressed(event)) { Dpad.LEFT -> { // Do something for LEFT direction press ... return true } Dpad.RIGHT -> { // Do something for RIGHT direction press ... return true } Dpad.UP -> { // Do something for UP direction press ... return true } ... } } // Check if this event is from a joystick movement and process accordingly. ... }
Java
Dpad dpad = new Dpad(); ... @Override public boolean onGenericMotionEvent(MotionEvent event) { // Check if this event if from a D-pad and process accordingly. if (Dpad.isDpadDevice(event)) { int press = dpad.getDirectionPressed(event); switch (press) { case LEFT: // Do something for LEFT direction press ... return true; case RIGHT: // Do something for RIGHT direction press ... return true; case UP: // Do something for UP direction press ... return true; ... } } // Check if this event is from a joystick movement and process accordingly. ... }
Processar movimentos do joystick
Quando os jogadores movem um joystick nos controles de jogos, o Android informa um
MotionEvent
que contém o
código de ação ACTION_MOVE
e as posições
atualizadas dos eixos do joystick. Seu jogo pode usar os dados fornecidos pelo
MotionEvent
para determinar se ocorreu um movimento do joystick.
Os eventos de movimento do joystick podem agrupar várias amostras de movimento
em um único objeto. O objeto MotionEvent
contém
a posição atual para cada eixo do joystick, bem como várias posições históricas
para cada eixo. Ao relatar eventos de movimento com o código de ação ACTION_MOVE
(como movimentos do joystick), o Android agrupa os
valores dos eixos para aumentar a eficiência. Os valores históricos de um eixo consistem no
conjunto de valores distintos mais antigos que o valor do eixo atual e mais recentes do que
os valores informados em qualquer evento de movimento anterior. Consulte a referência MotionEvent
para mais detalhes.
Use as informações históricas para renderizar com mais precisão o movimento
de um objeto do jogo com base na entrada do joystick. Para
recuperar os valores atuais e históricos, chame
getAxisValue()
ou getHistoricalAxisValue()
. Também é possível encontrar o número de pontos históricos no evento do joystick chamando getHistorySize()
.
O snippet abaixo mostra como você pode substituir o callback
onGenericMotionEvent()
para processar a entrada do joystick. Primeiro,
processe os valores históricos de um eixo e, em seguida, a posição atual dele.
Kotlin
class GameView(...) : View(...) { override fun onGenericMotionEvent(event: MotionEvent): Boolean { // Check that the event came from a game controller return if (event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK && event.action == MotionEvent.ACTION_MOVE) { // Process the movements starting from the // earliest historical position in the batch (0 until event.historySize).forEach { i -> // Process the event at historical position i processJoystickInput(event, i) } // Process the current movement sample in the batch (position -1) processJoystickInput(event, -1) true } else { super.onGenericMotionEvent(event) } } }
Java
public class GameView extends View { @Override public boolean onGenericMotionEvent(MotionEvent event) { // Check that the event came from a game controller if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) { // Process all historical movement samples in the batch final int historySize = event.getHistorySize(); // Process the movements starting from the // earliest historical position in the batch for (int i = 0; i < historySize; i++) { // Process the event at historical position i processJoystickInput(event, i); } // Process the current movement sample in the batch (position -1) processJoystickInput(event, -1); return true; } return super.onGenericMotionEvent(event); } }
Antes de usar a entrada do joystick, é necessário determinar se o joystick está centralizado e, em seguida, calcular os movimentos do eixo corretamente. Os joysticks normalmente têm uma área plana, ou seja, um intervalo de valores próximos à coordenada (0,0) em que o eixo é considerado centralizado. Se o valor do eixo relatado pelo Android estiver dentro da área plana, faça com que o controle esteja em repouso, ou seja, imóvel ao longo dos dois eixos.
O snippet abaixo mostra um método auxiliar que calcula o movimento ao longo
de cada eixo. Você invoca esse auxiliar no método processJoystickInput()
descrito mais abaixo.
Kotlin
private fun getCenteredAxis( event: MotionEvent, device: InputDevice, axis: Int, historyPos: Int ): Float { val range: InputDevice.MotionRange? = device.getMotionRange(axis, event.source) // A joystick at rest does not always report an absolute position of // (0,0). Use the getFlat() method to determine the range of values // bounding the joystick axis center. range?.apply { val value: Float = if (historyPos < 0) { event.getAxisValue(axis) } else { event.getHistoricalAxisValue(axis, historyPos) } // Ignore axis values that are within the 'flat' region of the // joystick axis center. if (Math.abs(value) > flat) { return value } } return 0f }
Java
private static float getCenteredAxis(MotionEvent event, InputDevice device, int axis, int historyPos) { final InputDevice.MotionRange range = device.getMotionRange(axis, event.getSource()); // A joystick at rest does not always report an absolute position of // (0,0). Use the getFlat() method to determine the range of values // bounding the joystick axis center. if (range != null) { final float flat = range.getFlat(); final float value = historyPos < 0 ? event.getAxisValue(axis): event.getHistoricalAxisValue(axis, historyPos); // Ignore axis values that are within the 'flat' region of the // joystick axis center. if (Math.abs(value) > flat) { return value; } } return 0; }
Juntando tudo, veja como você pode processar os movimentos do joystick no seu jogo:
Kotlin
private fun processJoystickInput(event: MotionEvent, historyPos: Int) { val inputDevice = event.device // Calculate the horizontal distance to move by // using the input value from one of these physical controls: // the left control stick, hat axis, or the right control stick. var x: Float = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_X, historyPos) if (x == 0f) { x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_X, historyPos) } if (x == 0f) { x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Z, historyPos) } // Calculate the vertical distance to move by // using the input value from one of these physical controls: // the left control stick, hat switch, or the right control stick. var y: Float = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Y, historyPos) if (y == 0f) { y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_Y, historyPos) } if (y == 0f) { y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_RZ, historyPos) } // Update the ship object based on the new x and y values }
Java
private void processJoystickInput(MotionEvent event, int historyPos) { InputDevice inputDevice = event.getDevice(); // Calculate the horizontal distance to move by // using the input value from one of these physical controls: // the left control stick, hat axis, or the right control stick. float x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_X, historyPos); if (x == 0) { x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_X, historyPos); } if (x == 0) { x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Z, historyPos); } // Calculate the vertical distance to move by // using the input value from one of these physical controls: // the left control stick, hat switch, or the right control stick. float y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Y, historyPos); if (y == 0) { y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_Y, historyPos); } if (y == 0) { y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_RZ, historyPos); } // Update the ship object based on the new x and y values }
Para oferecer suporte a controles de jogos que têm recursos mais sofisticados além de um único joystick, siga estas práticas recomendadas:
- Gerencie dois controles direcionais analógicos. Muitos controles de jogo têm
um joystick esquerdo e direito. Para o direcional analógico esquerdo, o Android
informa movimentos horizontais como eventos
AXIS_X
e movimentos verticais como eventosAXIS_Y
. Para o direcional analógico direito, o Android informa movimentos horizontais como eventosAXIS_Z
e movimentos verticais como eventosAXIS_RZ
. Lembre-se de processar os dois controles direcionais no seu código. - Processar os pressionamentos de gatilho superior, mas forneça métodos de entrada
alternativos. Alguns controles têm gatilhos de ombro
esquerdo e direito. Se esses acionadores estiverem presentes, o Android vai informar o pressionamento do acionador à esquerda
como um evento
AXIS_LTRIGGER
e o pressionamento do botão direito como um eventoAXIS_RTRIGGER
. No Android 4.3 (API de nível 18), um controle que produz umaAXIS_LTRIGGER
também informa um valor idêntico para o eixoAXIS_BRAKE
. O mesmo acontece paraAXIS_RTRIGGER
eAXIS_GAS
. O Android informa todos os pressionamentos de gatilhos analógicos com um valor normalizado de 0,0 (liberado) a 1,0 (totalmente pressionado). Nem todos os controles têm gatilhos. Portanto, considere permitir que os jogadores realizem essas ações com outros botões.