至于您的特定情况,您可能需要考虑使用某些 Windows API 来读取值(例如 XInput、UWP API)。作为奖励,这是我使用 Windows XInput API 读取控制器输入的一些错误。
#pragma comment(lib,"XInput.lib")
#pragma comment(lib,"Xinput9_1_0.lib")
#include <iostream>
#include <roapi.h>
#include <Xinput.h>
XINPUT_STATE fetchAConnectedJoystick()
{
DWORD dwResult;
XINPUT_STATE state;
for (DWORD i=0; i < XUSER_MAX_COUNT; i++)
{
ZeroMemory(&state, sizeof(XINPUT_STATE));
// Simply get the state of the controller from XInput.
dwResult = XInputGetState(i, &state);
// Controller is connected
if(dwResult == ERROR_SUCCESS)
{
return state;
}
}
std::exit;
}
void printLeftAnalogStickReadings(XINPUT_STATE state)
{
float LX = state.Gamepad.sThumbLX;
float LY = state.Gamepad.sThumbLY;
std::cout << "(X=" << LX << ", Y=" << LY << ")\n";
}
int computeAdjustedMagnitude(XINPUT_STATE state)
{
int INPUT_DEADZONE = 42;
float LX = state.Gamepad.sThumbLX;
float LY = state.Gamepad.sThumbLY;
float magnitude = sqrt(LX*LX + LY*LY); // Determine how far the controller is pushed
// Determine the direction the controller is pushed
float normalizedLX = LX / magnitude;
float normalizedLY = LY / magnitude;
if (magnitude > INPUT_DEADZONE) // Check if the controller is outside a circular dead zone
{
if (magnitude > 32767) magnitude = 32767; // Clip the magnitude at its expected maximum value
magnitude -= INPUT_DEADZONE; // Adjust magnitude relative to the end of the dead zone
}
else // If the controller is in the deadzone zero out the magnitude
{
magnitude = 0.0;
}
return magnitude;
}
int main()
{
XINPUT_STATE state;
int sleepDuration = 100; // Milliseconds
int adjustedMag = 0;
while (true) {
state = fetchAConnectedJoystick();
printLeftAnalogStickReadings(state);
// adjustedMag = computeAdjustedMagnitude(state);
// std::this_thread::sleep_for(std::chrono::milliseconds(sleepDuration));
}
}
从我最近对 Windows 内置操纵杆控制器校准工具的探索中,我可以确认 PS4 操纵杆上的以下行为(其他控制器的结果应该类似):
完成校准向导后,以下注册表将写入校准数据
HKEY_CURRENT_USER\System\CurrentControlSet\Control\MediaProperties\PrivateProperties\DirectInput\<DEVICE_ID>\Calibration\0\Type\Axes\<NUM>
,其中<NUM>
是轴号。对于 PS4 游戏杆,Windows 会读取六个轴,因此会创建六个注册表项值。轴的编号如下:
注册表项的格式
Calibration
映射到一个 12 字节的二进制值(编码为<MIN> <MID> <MAX>
)。例如,我的 Axis 0 (x) 具有值: <00 00 00 00> <80 00 00 00> <ff 00 00 00> 转换为Windows 所做的校准是将物理值转换为校准范围(上面的最小值、中间值、最大值)。例如,假设我有缺陷的左模拟摇杆的水平移动(x 轴)读数为 10-100,而它的范围应为 0-255。然后我可以将最小/最大值分别设置为 10 和 100 来校准有缺陷的模拟摇杆。
似乎没有针对死区的特定设置,所以我假设这是为上面的应用程序留下的实现细节(例如,对于游戏,定义为游戏逻辑代码的一部分)。
由于校准设置存储在注册表中,因此校准不会在不同机器之间持续存在。
至于您的特定情况,您可能需要考虑使用某些 Windows API 来读取值(例如 XInput、UWP API)。作为奖励,这是我使用 Windows XInput API 读取控制器输入的一些错误。
我相信校准信息存储在注册表中:
HKEY_CURRENT_USER\System\CurrentControlSet\Control\MediaProperties\PrivateProperties\DirectInput\<DEVICE>\Calibration
我不知道条目的格式是什么,但它不是人类可读的。