title:
aliases:
tags:
- cpp
category: 方法
stars:
url:
creation-time: 2024-02-04 20:03
modification-time: 2024-02-04 20:13:44
由于之前使用 MMSystem
库对手柄的数据进行读取 [[2023-10-17]] 的方式,在笔记本上接手柄总是出现一些虚拟手柄占用接口的问题(未找到原因)。另外找一种读取手柄数据的方式。
简单介绍一下使用 [[SDL]] 库读取手柄摇杆的方法。主要参考的源码是[1]。
初始化手柄子系统
bool init() {
// Initialization flag
bool success = true;
// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { // 源码里为了可视化手柄数值,进行了箭头绘制,所以额外初始化了一个video子系统
printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
success = false;
} else {
// Set texture filtering to linear
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) {
printf("Warning: Linear texture filtering not enabled!");
}
// Check for joysticks
if (SDL_NumJoysticks() < 1) {
printf("Warning: No joysticks connected!\n");
} else {
// Load joystick
gGameController = SDL_JoystickOpen(0);
if (gGameController == NULL) {
printf("Warning: Unable to open game controller! SDL Error: %s\n",
SDL_GetError());
}
}
}
return success;
}
手柄关闭子系统
void close() {
// Close game controller
SDL_JoystickClose(gGameController);
gGameController = NULL;
// Quit SDL subsystems
SDL_Quit();
}
主程序
int WinMain(int argc, char* args[]) {
// Start up SDL and create window
if (!init()) {
printf("Failed to initialize!\n");
} else {
bool quit = false;
// Event handler
SDL_Event e;
// Normalized direction
int xDir = 0;
int yDir = 0;
// While application is running
while (!quit) {
// Handle events on queue
while (SDL_PollEvent(&e) != 0) {
// User requests quit
if (e.type == SDL_QUIT) {
quit = true;
} else if (e.type == SDL_JOYAXISMOTION) {
// Motion on controller 0
if (e.jaxis.which == 0) {
std::cout<<"e.jaxis.axis: "<<e.jaxis.axis<<std::endl;
// X axis motion
if (e.jaxis.axis == 0) {
// Left of dead zone
if (e.jaxis.value < -JOYSTICK_DEAD_ZONE) {
xDir = e.jaxis.value;
}
// Right of dead zone
else if (e.jaxis.value > JOYSTICK_DEAD_ZONE) {
xDir = e.jaxis.value;
} else {
xDir = 0;
}
}
// Y axis motion
else if (e.jaxis.axis == 1) {
// Below of dead zone
if (e.jaxis.value < -JOYSTICK_DEAD_ZONE) {
yDir = e.jaxis.value;
}
// Above of dead zone
else if (e.jaxis.value > JOYSTICK_DEAD_ZONE) {
yDir = e.jaxis.value;
} else {
yDir = 0;
}
}
}
}
}
// Calculate angle
double joystickAngle = atan2((double)yDir, (double)xDir) * (180.0 / M_PI);
std::cout << "yDire: " << yDir << " xDir: " << xDir << std::endl;
// Correct angle
if (xDir == 0 && yDir == 0) {
joystickAngle = 0;
}
}
}
// Free resources and close SDL
close();
return 0;
}
关键的逻辑是,通过一个事件 SDL_Event
来表示摇杆是否运动,如果摇杆发生了运动,通过 axis
这个属性判断是 x
还是 y
方向的运动,然后保存到相应的摇杆位置状态值中。