如何区分方向键运动和操纵杆运动?
Posted
技术标签:
【中文标题】如何区分方向键运动和操纵杆运动?【英文标题】:How to differentiate a D-pad movement from a Joystick movement? 【发布时间】:2016-04-04 19:43:22 【问题描述】:我需要有两种不同的行为,一种用于方向键,另一种用于模拟操纵杆(在同一个游戏手柄上)。
问题是在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
是否可以识别正在使用的输入类型?怎么样?
【问题讨论】:
您找到解决方案了吗?我有同样的问题,但似乎没有办法区分这两种输入法。会很烦人... 似乎 DS4 控制器在您使用 DPAD 时不会声明 DPAD 源。您会得到一个操纵杆源事件,其帽子值设置为最小/最大值,具体取决于您按下的内容。无论如何,要支持 DS4,您似乎需要查询 X 和 XHat,看看哪个更大(abs)并使用它。 【参考方案1】:我遇到了同样的问题,我不得不深入研究this helpful Git user's project 以弄清楚他是如何做到的。区分不同操纵杆(和方向键)的方法是使用每个方向的特定轴。
如果您非常仔细地阅读android documentation's page(我没有注意到它),它确实显示了您如何区分各种操纵杆及其方向:
此图像显示左侧操纵杆使用轴 AXIS_X 和 AXIS_Y,而右侧操纵杆使用 AXIS_Z 和 AXIS_RZ。对于方向键,我使用了 AXIS_HAT_X 和 AXIS_HAT_Y。以下来自我的代码(在 Kotlin 中)的 sn-p 显示了如何单独访问其中的每一个:
注意:我还将搜索栏设置为 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)
【讨论】:
【参考方案2】:查看您提供的信息,它们看起来来自同一来源,即操纵杆 (0x1000010)。您可以在Input Device 对象上查看这些信息。
以下信息来自Handling Controller Actions:
要验证连接的输入设备是游戏控制器,请调用
getSources()
以获取该设备支持的输入源类型的组合位字段。
SOURCE_GAMEPAD
的源类型表示输入设备具有游戏手柄按钮(例如,BUTTON_A
)。请注意,尽管大多数游戏手柄通常具有方向控制,但此源类型并未严格指示游戏控制器是否具有方向键按钮。
SOURCE_DPAD
的源类型表示输入设备具有方向键按钮(例如,DPAD_UP
)。
SOURCE_JOYSTICK
的源类型表示输入设备具有模拟控制杆(例如,记录沿AXIS_X
和AXIS_Y
移动的操纵杆)。
您可能还想查看Supporting Multiple Controller Input。
【讨论】:
我需要区分两个不同的输入(dpad 和模拟)来自同一个操纵杆源,而不是两个不同的源【参考方案3】:来自 Android 文档 (https://developer.android.com/training/game-controllers/controller-input):
Android 将 D-pad UP 和 DOWN 按下报告为 AXIS_HAT_Y 事件,并带有 范围从 -1.0(向上)到 1.0(向下),方向键向左或向右按下 AXIS_HAT_X 事件,范围从 -1.0(左)到 1.0(右)。
一些控制器会使用键代码报告方向键按下。如果你的游戏关心方向键,你应该处理帽子轴 事件和方向键键代码作为相同的输入事件,如 推荐在表 2 中。
我使用过的两个控制器(NVIDIA SHIELD 蓝牙和 Microsoft XBOX360 有线)都生成 AXIS_HAT_* 运动事件。
【讨论】:
DS4 也是如此。 DPad 始终是 MotionEvent,source=Joystick,必须从 XHat/YHat 值中读取 DPad。以上是关于如何区分方向键运动和操纵杆运动?的主要内容,如果未能解决你的问题,请参考以下文章