我需要有两种不同的行为,一种用于D-pad,另一种用于模拟操纵杆(在同一个游戏手柄上)。
问题在于onGenericMotionEvent
回调,两者在MotionEvent
上都有相同的信息,我无法区分它们。
// d-pad
MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=-1.5259255E-5, y[0]=-1.5259255E-5, toolType[0]=TOOL_TYPE_UNKNOWN, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=151637936, downTime=0, deviceId=5, source=0x1000010 }
// analog joystick
MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=0.64507514, y[0]=0.710811, toolType[0]=TOOL_TYPE_UNKNOWN, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=151650802, downTime=0, deviceId=5, source=0x1000010 }
是否可以识别正在使用哪种输入?怎么样?
答案 0 :(得分:0)
查看您提供的信息,它们看起来来自同一来源,即操纵杆(0x1000010)。您可以在Input Device对象上查看这些信息。
以下信息来自Handling Controller Actions:
要验证连接的输入设备是游戏控制器,请调用
getSources()
以获取该设备支持的输入源类型的组合位字段。源类型
SOURCE_GAMEPAD
表示输入设备具有游戏手柄按钮(例如,BUTTON_A
)。请注意,此源类型并未严格指示游戏控制器是否具有D-pad按钮,尽管大多数游戏手柄通常都有方向控制。源类型
SOURCE_DPAD
表示输入设备具有D-pad按钮(例如,DPAD_UP
)。源类型
SOURCE_JOYSTICK
表示输入设备具有模拟控制杆(例如,记录AXIS_X
和AXIS_Y
移动的操纵杆。 p>
答案 1 :(得分:0)
从Android文档(https://developer.android.com/training/game-controllers/controller-input):
Android将D-pad的上,下按下报告为AXIS_HAT_Y事件,并带有 范围从-1.0(向上)到1.0(向下),并且按D-pad的LEFT或RIGHT按下 AXIS_HAT_X事件,范围从-1.0(左)到1.0(右)。
有些控制器则报告带有按键代码的D-pad按下情况。如果您的游戏关心的是D-pad按压,则应该处理帽子轴 事件和D-pad键代码与输入事件相同 在表2中推荐。
我使用过的两个控制器(NVIDIA SHIELD BlueTooth和Microsoft XBOX360有线)都生成AXIS_HAT_ *运动事件。
答案 2 :(得分:0)
我遇到了同样的问题,我不得不深入研究this helpful Git user's project以弄清楚他是如何做到的。区分不同操纵杆(和D-pad)的方法是使用每个方向的特定轴。
如果您非常仔细地阅读了Android documentation's page(我没读过),它确实说明了如何区分各种操纵杆及其方向:
此图像显示左操纵杆使用轴 AXIS_X 和 AXIS_Y ,而右操纵杆使用 AXIS_Z 和 AXIS_RZ < / strong>。对于D-pad,我使用了 AXIS_HAT_X 和 AXIS_HAT_Y 。我的代码中的以下代码段(在Kotlin中)显示了如何分别访问每个代码:
注意:我也将搜索栏设置为0-100,这就是为什么在processJoystickInput()
的底部设置了转换数学。
private fun processJoystickInput(event: MotionEvent, historyPos: Int) {
val inputDevice = event.device
val newJoystickValues = floatArrayOf(
getCenteredAxis(event, inputDevice, MotionEvent.AXIS_X, historyPos),
getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Y, historyPos),
getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Z, historyPos),
getCenteredAxis(event, inputDevice, MotionEvent.AXIS_RZ, historyPos),
getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_X, historyPos),
getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_Y, historyPos))
// Update based on the new x and y values
val throttleSeekBar = findViewById<SeekBar>(R.id.throttle_seekBar)
val yawSeekBar = findViewById<SeekBar>(R.id.yaw_seekBar)
val pitchSeekBar = findViewById<SeekBar>(R.id.pitch_seekBar)
val rollSeekBar = findViewById<SeekBar>(R.id.roll_seekBar)
val dpadXSeekBar = findViewById<SeekBar>(R.id.dpadX_seekBar)
val dpadYSeekBar = findViewById<SeekBar>(R.id.dpadY_seekBar)
// Convert the float range (-1.00 to 1.00) to Int (0 to 100)
yawSeekBar.progress = ((newJoystickValues[0] + 1) * 50).toInt()
throttleSeekBar.progress = ((newJoystickValues[1] + 1) * 50).toInt()
rollSeekBar.progress = ((newJoystickValues[2] + 1) * 50).toInt()
pitchSeekBar.progress = ((newJoystickValues[3] + 1) * 50).toInt()
dpadXSeekBar.progress = ((newJoystickValues[4] + 1) * 50).toInt()
dpadYSeekBar.progress = ((newJoystickValues[5] + 1) * 50).toInt()
}
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)
}
}