我正在尝试使用 DirectInput API 在我的应用程序中使用各种游戏手柄控制器。据我所知,轴在设备之间的映射方式不同。
除了使用 DeviceInformation.ProductName/InstanceName 来区分控制器以允许不同的轴控制分配之外,是否有一种通用的实践方法来确定控制器类型?
我正在尝试使用 DirectInput API 在我的应用程序中使用各种游戏手柄控制器。据我所知,轴在设备之间的映射方式不同。
除了使用 DeviceInformation.ProductName/InstanceName 来区分控制器以允许不同的轴控制分配之外,是否有一种通用的实践方法来确定控制器类型?
如果您只需要知道控制器类型(FirstPerson、Joystick、Gamepad...),请使用 DeviceInformation.DeviceType。
要知道连接了哪个特定控制器,请使用 ProductName 或更好的 ProductGuid。对于两个不同的控制器,ProductName 可能相同。另一方面,即使对于相同生产费用的两个控制器,ProductGuid 也可能不同。
只有使用 ProductGuid,您才能毫无疑问地识别连接的设备实例。
有人可能会尝试遍历dev.GetObjects(DeviceObjectTypeFlags.Axis)
并检查轴的名称(和偏移量),但不能保证名为“X 轴”的轴确实映射到someDevice.CurrentJoystickState.X
.
您要么必须自己为将要连接的任何控制器预先完成所有映射(只有在您自己开发应用程序时才可接受)并将该信息存储在应用程序的配置文件中,否则您需要提供用户可以自己映射新设备的某种形式。我目前正在开发这个,但这个答案将超出这个问题的范围......
还请考虑,为了获得此基本信息(如 ProductGuid),您不必创建设备。这些属性已在 DeviceInstance 中可用(在 Microsoft.DirectX.DirectInput.Manager.GetDevices() 的 DeviceList 中)...
更新:因为我自己的回答一直困扰着我,所以我更深入地研究了这个话题。
因此,这是一种确定哪些轴映射到哪些值的方法:
// loop through the axes of an acquired device:
foreach (DeviceObjectInstance doi in
_currentDevice.GetObjects(DeviceObjectTypeFlags.Axis))
{
doi.Name; // the name of the axis, e.g. 'X-Achse' (that's a german device...)
doi.Offset / 4; // the enumeration 'index' of the axis
doi.UsagePage; // the UsagePage determines the context of the axis value
// vvvv
doi.Usage; // the Usage tells you which JoystickState field to map to.
// ^^^^
}
到目前为止,我发现了这些使用价值表示:
(with JoystickState s = _currentDevice.CurrentJoystickState)
Usage Axis value
48 s.X
49 s.Y
50 s.Z
51 s.Rx
52 s.Ry
53 s.Rz
54 s.GetSlider()[0]
所以使用 aswitch(doi.Usage)
可以自动得到对应的轴值。