首页 > 其他分享 >使用SDL库读取手柄摇杆数据

使用SDL库读取手柄摇杆数据

时间:2024-02-04 20:34:39浏览次数:36  
标签:jaxis 手柄 else 摇杆 printf SDL

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 方向的运动,然后保存到相应的摇杆位置状态值中。

Reference


  1. Lazy Foo' Productions - Gamepads and Joysticks ↩︎

标签:jaxis,手柄,else,摇杆,printf,SDL
From: https://www.cnblogs.com/pomolnc/p/18006948

相关文章

  • 吉利汽车:S-SDLC融入开发体系,推动智能汽车安全发展
    吉利汽车是中国汽车行业的知名品牌,是一家具有国际化视野的汽车企业,在中国汽车市场自主品牌中占据领军地位。吉利汽车集团数字化中心利用数字化技术优势赋能业务升级,推动研发效率提升和产品安全能力拓展,进行整体数字化转型。在数字化转型过程,为了应对软件开发面临的种种风险,吉利汽车......
  • Sunshine+Moonlight+Android手机串流配置(局域网、无手柄)
    目录前言Sunshine(服务端)ApplicationConfigurationGeneralAdvanceMoonlight(客户端)配对打开虚拟手柄串流按键调整退出串流原神,启动!前言  写这篇文章单纯是因为搜来搜去没有很符合我需求的教程,好在两个软件的配置足够简单一次成功,所以分享一下我的配置。  我的需求就是局域网......
  • webservice soap wsdl文件 学习
    WebServicesDescriptionLanguage,是为WSDLportTypes用于定义操作,包括多个operation(理解为函数),定义了操作的输入和输出数据流中可以出现的XML消息message理解operation所使用的参数集,内部每个part都是一个子参数,part中引用各种已定义的type的数据来定义各个子参数operation为......
  • 【Unity】在游戏中实现虚拟摇杆功能
    使用场景在手机游戏开发中,使用虚拟摇杆控制角色进行移动。虚拟摇杆预制体制作在UI界面添加虚拟摇杆外圈图片在外圈下添加内圈图片将位置置于外圈中心位置添加脚本usingTools;usingUnityEngine;///<summary>///虚拟摇杆管理器///</summary>......
  • @WebServiceClient wsdlLocation 动态给注解内容参数赋值
    动态给注解内容参数赋值@WebServiceClient(name="IXxxService",targetNamespace="http://xxx.xxx.xxx.com",wsdlLocation="${WSDL_URL}")publicclassIXxxServiceextendsService{ //静态变量在静态代码块加载后加载,且注解也在之后加载,完成动态注入修改注解里的参......
  • SDL2+FFmpeg5.0播放视频文件
    一、概述上一节使用SDL2播放了YUV视频文件,本节使用SDL2+FFmpeg5.0播放一个视频文件(只播放视频,不播放声音)播放效果图: 二、代码示例#include"sdl_ffmpeg_play.h"//sdl刷新事件#defineSFM_REFRESH_EVENT(SDL_USEREVENT+1)//sdl退出事件#defineSFM_BREAK......
  • SDL2+SDL_Thread+SDL_Event实现yuv文件的播放
    一、概述上一节使用单线程播放了YUV文件。在一个线程中播放yuv文件逻辑看起来简单,但是会产生一些问题。如:视频卡顿、无响应等问题。本节在上一节的基础上对播放YUV文件的代码进行改造,加入SDL_Event和SDL_Thread。使SDL_Thread现成发出命令时刷新YUV视频帧。等收到结束命......
  • SDL播放YUV数据
    一、概述上一节使用SDL2在窗口上显示了一张图片,本节使用SDL2播放YUV420P数据。YUV420P一帧数据的长度=width*height*3/2二、代码示例下面这段示例代码读取YUV数据和现实YUV数据都是在同一个线程中的。播放是能播放,但是会很卡,不一会儿就会出现无响应的情况。下一节......
  • SDL事件之简单退出事件SDL_QUIT
    一、概述上一篇使用SDL加载了一张图片,图片展示后3秒窗口会自动关闭,如果不想让窗口自动关闭,而是用户自己指定啥时候关闭就啥时候关闭,该怎么弄?那就有必要加上SDL的事件了。加入一个简单的SDL事件非常简单。以点击X号关闭窗口为例:1.初始化SDL事件//初始化......
  • SDL2加载一个图片
    一、概述使用SDL2+SDL2_Image显示一张图片操作步骤:SDL2的操作流程:1.初始化SDLSDL_Init2.创建SDL_WindowSDL_CreateWindow3.创建渲染器SDL_RendererSDL_CreateRenderer4.生成一个SDL_Surface,这个Surfac......