在系統層級,Android 會將遊戲控制器的輸入事件代碼回報為 Android 鍵碼和軸值。在遊戲中,您可以接收這些代碼和值,並將其轉換為特定遊戲內動作。
當玩家實際連結遊戲控制器或以無線方式將遊戲控制器與 Android 裝置配對時,系統就會自動將控制器偵測為輸入裝置,並開始回報輸入事件。遊戲可以在有效的 Activity
或已聚焦的 View
中實作下列回呼方法,以便接收這些輸入事件 (您應為 Activity
或 View
實作回呼,但不能同時為兩者實作):
- 自
Activity
起:dispatchGenericMotionEvent(android.view. MotionEvent)
呼叫可處理一般動作事件,例如搖桿動作。
dispatchKeyEvent(android.view.KeyEvent)
用於處理按鍵事件,例如按下或釋放遊戲控制器或方向鍵按鈕。
View
發送:onGenericMotionEvent(android.view.MotionEvent)
呼叫可處理一般動作事件,例如搖桿動作。
onKeyDown(int, android.view.KeyEvent)
呼叫此動作可處理實體按鍵 (例如遊戲手把或 D-Pad 按鈕) 的按下動作。
onKeyUp(int, android.view.KeyEvent)
呼叫可處理實體按鍵 (例如遊戲手把或 D-Pad 按鈕) 的版本。
建議的方法是從使用者互動的特定 View
物件擷取事件。檢查回呼提供的下列物件,以取得所收到輸入事件類型的相關資訊:
KeyEvent
- 用於說明方向鍵 (D-Pad) 和遊戲手把按鈕事件的物件。按鍵事件會隨附按鍵碼,用來指出觸發的特定按鈕,例如
DPAD_DOWN
或BUTTON_A
。您可以呼叫getKeyCode()
或從onKeyDown()
等按鍵事件回呼取得按鍵代碼。 MotionEvent
- 這個物件用於說明搖桿和肩膀觸發動作的輸入內容。動作事件會隨附動作代碼和一組軸值。動作碼會指定發生的狀態變更,例如搖桿移動。軸值會說明特定實體控制項 (例如
AXIS_X
或AXIS_RTRIGGER
) 的位置和其他移動屬性。呼叫getAxisValue()
即可取得動作程式碼,呼叫getAction()
和軸值。
本課程將著重於如何在遊戲畫面中,透過實作上述的 View
回呼方法及處理 KeyEvent
和 MotionEvent
物件,處理最常見類型的實體控制項 (遊戲控制器按鈕、方向鍵和搖桿) 輸入內容。
確認遊戲控制器已連線
回報輸入事件時,Android 不會區分非遊戲控制器裝置的事件和來自遊戲控制器的事件。舉例來說,觸控螢幕動作會產生 AXIS_X
事件,代表觸控表面的 X 座標,但搖桿會產生 AXIS_X
事件,代表搖桿的 X 位置。如果您的遊戲需要處理遊戲控制器輸入,請先檢查輸入事件是否來自相關的來源類型。
如要確認已連結的輸入裝置是否為遊戲控制器,請呼叫 getSources()
來取得該裝置支援的輸入來源類型合併位元欄位。接著,您可以測試下列欄位是否設定完成:
- 來源類型為
SOURCE_GAMEPAD
表示輸入裝置有遊戲手把按鈕 (例如BUTTON_A
)。請注意,這個來源類型並不會明確指出遊戲控制器是否有 D-Pad 按鈕,但大多數遊戲手把通常都會提供方向控制項。 - 來源類型為
SOURCE_DPAD
表示輸入裝置有方向鍵按鈕 (例如DPAD_UP
)。 SOURCE_JOYSTICK
來源類型表示輸入裝置具有類比控制桿 (例如,記錄AXIS_X
和AXIS_Y
沿途動作的搖桿)。
下列程式碼片段是輔助方法,可讓您檢查已連結的輸入裝置是否為遊戲控制器。如果是的話,這個方法會擷取遊戲控制器的裝置 ID。接著,您可以將每個裝置 ID 與遊戲中的玩家建立關聯,並分別處理每位已連線玩家的遊戲動作。如要進一步瞭解如何支援在同一部 Android 裝置上同時連接多個遊戲控制器,請參閱「支援多個遊戲控制器」。
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; }
此外,建議您檢查連線遊戲控制器支援的個別輸入功能。舉例來說,如果您想讓遊戲只使用所瞭解的實體控制項組合中的輸入內容,這項功能就能派上用場。
如要偵測連接的遊戲控制器是否支援特定按鍵代碼或軸代碼,請使用下列技巧:
- 在 Android 4.4 (API 級別 19) 以上版本中,您可以呼叫
hasKeys(int...)
,判斷已連結的遊戲控制器是否支援某個按鍵代碼。 - 在 Android 3.1 (API 級別 12) 以上版本中,您可以先呼叫
getMotionRanges()
,找出已連結遊戲控制器所支援的所有可用軸。接著,針對每個傳回的InputDevice.MotionRange
物件,呼叫getAxis()
以取得其軸 ID。
處理遊戲手把按鈕的按下動作
圖 1 顯示 Android 如何將按鍵碼和軸值對應至大多數遊戲控制器的實體控制項。
圖中的圖說如下:
按下遊戲控制器按鈕時產生的常見按鍵代碼包括 BUTTON_A
、BUTTON_B
、BUTTON_SELECT
和 BUTTON_START
。當使用者按下 D-Pad 跨列的中心點時,部分遊戲控制器也會觸發 DPAD_CENTER
按鍵程式碼。遊戲可以藉由呼叫 getKeyCode()
或主要事件回呼 (例如 onKeyDown()
) 來檢查按鍵程式碼;如果遊戲代表與遊戲相關的事件,則將其視為遊戲動作來處理。表 1 列出最常見遊戲搖桿按鈕的建議遊戲動作。
遊戲動作 | 按鈕鍵碼 |
---|---|
在主選單中開始遊戲,或在遊戲期間暫停/取消暫停 | BUTTON_START *。 |
顯示選單 | BUTTON_SELECT * 和 KEYCODE_MENU * |
與「導覽」設計指南中所述的 Android 返回導覽行為相同。 | KEYCODE_BACK |
返回選單中的上一個項目 | BUTTON_B |
確認選取項目或執行主要遊戲動作 | BUTTON_A 和 DPAD_CENTER |
* 遊戲不應依賴「開始」、「選取」或「選單」按鈕的存在。
提示: 請考慮在遊戲中提供設定畫面,讓使用者能針對遊戲動作自訂自己的遊戲控制器對應關係。
以下程式碼片段說明如何覆寫 onKeyDown()
,將按下的 BUTTON_A
和 DPAD_CENTER
按鈕與遊戲動作建立關聯。
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; } }
注意:在 Android 4.2 (API 級別 17) 以下版本中,系統會將 BUTTON_A
視為 Android Back 鍵。如果您的應用程式支援這些 Android 版本,請務必將 BUTTON_A
視為主要遊戲動作。如要判斷裝置目前的 Android SDK 版本,請參閱 Build.VERSION.SDK_INT
值。
處理方向鍵輸入
4 向方向鍵 (D-Pad) 是許多遊戲控制器中常見的實體控制項。Android 會將 D-pad 向上和向下按鈕的按壓動作,記錄為範圍為 -1.0 (向上) 到 1.0 (向下) 的 AXIS_HAT_Y
事件,並將 D-pad 向左或向右按鈕的按壓動作,記錄為範圍為 -1.0 (向左) 到 1.0 (向右) 的 AXIS_HAT_X
事件。
部分控制器會透過按鍵碼回報 D-Pad 的按下動作。如果您的遊戲重視 D-Pad 的按下動作,則應將帽子軸事件和 D-Pad 的按鍵碼視為與表 2 建議相同的輸入事件。
遊戲動作 | D-Pad 按鍵碼 | 帽軸代碼 |
---|---|---|
往上移動 | KEYCODE_DPAD_UP |
AXIS_HAT_Y (適用於 0 到 -1.0 的值) |
往下移動 | KEYCODE_DPAD_DOWN |
AXIS_HAT_Y (值介於 0 到 1.0) |
向左移 | KEYCODE_DPAD_LEFT |
AXIS_HAT_X (適用於值 0 到 -1.0) |
向右移 | KEYCODE_DPAD_RIGHT |
AXIS_HAT_X (值為 0 到 1.0) |
以下程式碼片段顯示輔助類別,可讓您檢查輸入事件的帽軸和按鍵碼值,藉此判斷 D-Pad 的方向。
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; } } }
您可以在遊戲中,針對要處理 D-Pad 輸入的任何位置 (例如 onGenericMotionEvent()
或 onKeyDown()
回呼),使用這個輔助類別。
例如:
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. ... }
處理搖桿移動
當玩家在遊戲控制器上移動搖桿時,Android 會回報包含 ACTION_MOVE
動作程式碼的 MotionEvent
,以及搖桿軸的更新位置。遊戲可以利用 MotionEvent
提供的資料,判斷搖桿是否重視。
請注意,搖桿動作事件可在單一物件中批次批次處理多個動作樣本。MotionEvent
物件包含每個搖桿的目前位置,以及每個軸的多個歷史位置。回報含有動作程式碼 ACTION_MOVE
的動作事件 (例如搖桿動作) 時,Android 會批次處理軸值,藉此提升效率。軸的歷來值包含一組不同值,這些值的時間早於目前軸的值,但晚於先前任何動作事件中回報的值。詳情請參閱 MotionEvent
參考資料。
您可以利用歷史資訊,根據搖桿輸入內容更準確地轉譯遊戲物件的動作。如要擷取目前和歷來的值,請呼叫 getAxisValue()
或 getHistoricalAxisValue()
。您也可以透過呼叫 getHistorySize()
查看搖桿事件中的歷史點數。
下列程式碼片段說明如何覆寫 onGenericMotionEvent()
回呼以處理搖桿輸入內容。您應先處理軸的歷史值,然後再處理其目前位置。
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); } }
使用搖桿輸入功能之前,您需要先判斷搖桿是否置中,然後據此計算軸的移動。搖桿通常會有一個平坦的區域,也就是 (0,0) 座標附近的值範圍,系統會將該區域視為軸心。如果 Android 回報的軸值落在平坦區域內,您應將控制器視為處於靜止狀態 (也就是沿著兩個軸不動)。
以下程式碼片段顯示輔助方法,可計算沿著每個軸線的移動情形。您可以在 processJoystickInput()
方法中叫用這個輔助程式,如下文所述。
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; }
總結來說,以下說明如何處理遊戲中的搖桿動作:
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 }
如要支援遊戲控制器 (除了單一搖桿之外,還提供更精密的功能),請遵循下列最佳做法:
- 處理雙控制器搖桿。許多遊戲控制器都有左右搖桿。對於左側搖桿,Android 會將水平移動動作記錄為
AXIS_X
事件,垂直移動動作則記錄為AXIS_Y
事件。針對右搖桿,Android 會將水平動作回報為AXIS_Z
事件,而垂直動作則會以AXIS_RZ
事件的形式回報。請務必在程式碼中處理兩個控制器搖桿。 -
處理肩觸發的按下動作,並確保遊戲支援
AXIS_
和KEYCODE_BUTTON_
事件。部分控制器有左右肩部觸發器。如果有這些觸發條件,就會發出AXIS_*TRIGGER
和/或KEYCODE_BUTTON_*2
事件。左邊的扳機鍵則是AXIS_LTRIGGER
和KEYCODE_BUTTON_L2
。正確的觸發條件為AXIS_RTRIGGER
和KEYCODE_BUTTON_R2
。只有在觸發器發出 0 到 1 之間的值範圍時,才會發生軸向事件,而某些具有類比輸出的控制器除了軸向事件外,還會發出按鈕事件。遊戲必須同時支援AXIS_
和KEYCODE_BUTTON_
事件,才能與所有常見的遊戲控制器相容。如果控制器同時回報這兩種事件,請選擇最適合遊戲玩法的事件。在 Android 4.3 (API 級別 18) 以上版本中,產生AXIS_LTRIGGER
的控制器也會回報AXIS_BRAKE
軸的相同值。AXIS_RTRIGGER
和AXIS_GAS
也是如此。Android 會以 0.0 (已釋放) 到 1.0 (已完全按下) 的正規化值,回報所有類比觸發器按下事件。 -
在模擬環境中,特定行為和支援功能可能會有所不同。模擬平台 (例如 Google Play 遊戲) 的行為可能會因主機作業系統的功能而略有不同。舉例來說,有些同時發出
AXIS_
和KEYCODE_BUTTON_
事件的控制器只會發出AXIS_
事件,而且對部分控制器的支援功能可能完全遺失。