如何区分D-pad运动与操纵杆运动?

时间:2015-12-30 19:47:14

标签: android android-tv gamepad

我需要有两种不同的行为,一种用于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 }

是否可以识别正在使用哪种输入?怎么样?

3 个答案:

答案 0 :(得分:0)

查看您提供的信息,它们看起来来自同一来源,即操纵杆(0x1000010)。您可以在Input Device对象上查看这些信息。

以下信息来自Handling Controller Actions

  

要验证连接的输入设备是游戏控制器,请调用getSources()以获取该设备支持的输入源类型的组合位字段。

     

源类型SOURCE_GAMEPAD表示输入设备具有游戏手柄按钮(例如,BUTTON_A)。请注意,此源类型并未严格指示游戏控制器是否具有D-pad按钮,尽管大多数游戏手柄通常都有方向控制。

     

源类型SOURCE_DPAD表示输入设备具有D-pad按钮(例如,DPAD_UP)。

     

源类型SOURCE_JOYSTICK表示输入设备具有模拟控制杆(例如,记录AXIS_XAXIS_Y移动的操纵杆。

您可能还想查看Supporting Multiple Controller Input

答案 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(我没读过),它确实说明了如何区分各种操纵杆及其方向:

Android documentation for different axis/labels

此图像显示左操纵杆使用轴 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)
    }
}