支持多个游戏控制器

虽然大多数游戏的设计宗旨是让每台 Android 设备支持一个用户, 我们还可以使用 同时连接了同一台 Android 设备。

本课介绍了在单个 API 中处理输入的一些基本技巧, 支持通过多个已连接的控制器畅玩设备多人游戏。这包括 保持玩家头像和每个控制器设备之间的映射, 正确处理控制器输入事件。

将玩家映射到控制器设备 ID

当游戏控制器连接到 Android 设备时,系统 会为其分配一个整数设备 ID。您可以获取已连接的 游戏控制器,如验证游戏控制器是否已连接中所示。InputDevice.getDeviceIds()然后,您可以将每个 设备 ID,并分别处理每个玩家的游戏操作。

注意 :在搭载 Android 4.1 (API) 的设备上 级别 16)及更高版本,则可使用 getDescriptor(),此方法会返回一个唯一的 输入设备的永久性字符串值。与设备 ID 不同 即使输入设备断开连接、重新连接或 重新配置。

以下代码段展示了如何使用 SparseArray 将玩家的头像与特定控制器相关联。在此示例中, mShips 变量用于存储 Ship 对象的集合。一种新的 当用户连接新控制器时,系统会在游戏中创建玩家头像; 并在其关联的控制器被移除时移除。

onInputDeviceAdded()onInputDeviceRemoved() 回调 方法属于 <ph type="x-smartling-placeholder"></ph> 跨 Android 版本支持控制器。通过实施这些 监听器回调时,您的游戏可以在发生 添加或移除了控制器此检测功能与 Android 2.3 兼容 (API 级别 9)及更高版本。

Kotlin

private val ships = SparseArray<Ship>() override fun onInputDeviceAdded(deviceId: Int) {  getShipForID(deviceId) } override fun onInputDeviceRemoved(deviceId: Int) {  removeShipForID(deviceId) } private fun getShipForID(shipID: Int): Ship {  return ships.get(shipID) ?: Ship().also {  ships.append(shipID, it)  } } private fun removeShipForID(shipID: Int) {  ships.remove(shipID) }

Java

private final SparseArray<Ship> ships = new SparseArray<Ship>(); @Override public void onInputDeviceAdded(int deviceId) {  getShipForID(deviceId); } @Override public void onInputDeviceRemoved(int deviceId) {  removeShipForID(deviceId); } private Ship getShipForID(int shipID) {  Ship currentShip = ships.get(shipID);  if ( null == currentShip ) {  currentShip = new Ship();  ships.append(shipID, currentShip);  }  return currentShip; } private void removeShipForID(int shipID) {  ships.remove(shipID); }

处理多控制器输入

您的游戏应执行以下循环以处理 来自多个控制器的输入源:

  1. 检测是否发生输入事件。
  2. 识别输入源及其设备 ID。
  3. 根据输入事件键码或轴值所指示的操作, 更新与该设备 ID 相关联的玩家头像。
  4. 渲染并更新界面。

KeyEventMotionEvent 输入 事件具有与其相关联的设备 ID。您的游戏可以利用 以确定输入事件来自哪个控制器,并更新 与该控制器相关联的玩家头像。

以下代码段展示了如何获取玩家头像引用 游戏控制器设备 ID 对应的操作,并根据 按钮。

Kotlin

override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {  if (event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD) {  event.deviceId.takeIf { it != -1 }?.also { deviceId ->  val currentShip: Ship = getShipForID(deviceId)  // Based on which key was pressed, update the player avatar  // (e.g. set the ship headings or fire lasers)  return true  }  }  return super.onKeyDown(keyCode, event) }

Java

@Override public boolean onKeyDown(int keyCode, KeyEvent event) {  if ((event.getSource() & InputDevice.SOURCE_GAMEPAD)  == InputDevice.SOURCE_GAMEPAD) {  int deviceId = event.getDeviceId();  if (deviceId != -1) {  Ship currentShip = getShipForId(deviceId);  // Based on which key was pressed, update the player avatar  // (e.g. set the ship headings or fire lasers)  ...  return true;  }  }  return super.onKeyDown(keyCode, event); }

注意 :根据最佳做法,当用户的 您应暂停游戏并询问用户是否 想要重新连接。