【问题标题】:Joystick won't work using SDL操纵杆无法使用 SDL
【发布时间】:2013-01-27 00:56:35
【问题描述】:

我正在用 SDL 构建一个简单的游戏。我经历了无数的教程,我显然错过了一些东西,因为它仍然完全忽略了我的操纵杆

在我的构造函数中

SDL_JoystickEventState(SDL_ENABLE);
joystick = SDL_JoystickOpen(0);

在我的更新中,我正在调用一个测试来检查我是否真的初始化了操纵杆

if (SDL_NumJoysticks() <= 0)
{
done = true;
}

这也是我的播放器更新

void World::playerMovement()
{
    SDL_Event event;

    while (SDL_PollEvent (&event))
    {
        switch (event.type)
        {
            case SDL_QUIT:
                done = true;
                break;
            case SDL_JOYAXISMOTION:
                if ( ( event.jaxis.value < -3200 ) || (event.jaxis.value > 3200 ) )
                {
                    test = true;
                }
                    break;
        }
   }
}

Test 只是一个布尔值,一旦为真将意味着我的敌人开始生成。我还检查了 main

if (SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK ) < 0)
{
    fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
    done = true;
}

当我运行游戏时,它会正常加载,但无论我如何移动操纵杆,它都不会将 test 设置为 true。

我也尝试在 while poll 事件循环中使用以下内容。

if (event.type == SDL_JOYAXISMOTION)
{
if(SDL_JoystickGetAxis(joystick, 1) > 0)
{
test = true;
}
}

任何想法是我错过了什么?

【问题讨论】:

    标签: events sdl joystick


    【解决方案1】:

    我认为 emartel 拥有确保 SDL_joystick 正常工作的最佳答案。

    World::playerMovement() 什么时候发生?从这些 sn-ps 很难确定程序的整体流程。

    我很高兴与您分享我处理操纵杆的代码,该代码跟踪:多个操纵杆、轴缩放 [-1,1] 并删除了死区以及按住按钮。

    下面是如何将其用作主循环的一部分的 sn-p:

    // FIXME: SDL needs to be initialized before we get here.
    
    JoystickManager Joy;
    Joy.Initialize();
    double deadzone = 0.02;
    
    // Main loop.
    bool done = false;
    while( ! done )
    {
        // Keep the list of joysticks up-to-date.
        Joy.FindJoysticks();
    
        // Handle all user input.
        SDL_Event event;
        while( SDL_PollEvent( &event ) )
        {
            // Let the JoystickManager track events relevant to it.
            Joy.TrackEvent( &event );
    
            // FIXME: Handle single-press events here (next target, etc).
            // Don't handle button-held-down events like firing (see below).
    
            if( event.type == SDL_QUIT )
                done = true;
        }
    
        // Read joystick 0 analog axes.
        double roll = Joy.Axis( 0, 0, deadzone );
        double pitch = Joy.Axis( 0, 1, deadzone );
        double yaw = Joy.Axis( 0, 3, deadzone );
        double throttle = Joy.AxisScaled( 0, 2, 1., 0., 0., deadzone );
    
        // Read joystick 0 buttons held down.
        bool firing = Joy.ButtonDown( 0, 0 );
    
        // FIXME: Update game objects and draw graphics.
    }
    

    【讨论】:

    • @user2014680 另一个想法;你有两个不同的循环调用 SDL_PollEvent 吗?无论您是否使用我的代码,都应该只有一个。每次调用 SDL_PollEvent(&event) 时,它都会为您提供事件数据并将其从队列中删除。因此,通过 SDL_PollEvent 的第二次循环将看不到已删除的事件。
    【解决方案2】:

    我在 SDL2 中发现了一个奇怪的行为:

    如果没有事件放入队列,请尝试在 SDL_Init 调用之前添加以下内容:

    SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,"1");
    

    【讨论】:

    • 这能回答 OP 的问题吗?也许您可以编辑您的答案并扩展它如何适合 OP 的场景?
    • 谢谢!!!这正是我的问题。我意识到这是因为我没有创建一个窗口,只是一个控制台。所以没有什么可以关注的。允许捕获后台事件解决了我的问题。
    【解决方案3】:

    您确定joystick 指向有效的操纵杆吗?

    您声明您在您的Constructor 中获取它...在您使用SDL_INIT_JOYSTICK 初始化SDL 之前是否碰巧调用了该构造函数?如果您的播放器是全局变量,则可能会发生这种情况。

    确保按照您的顺序:

    • 通过使用| SDL_INIT_JOYSTICK 将其添加到您的SDL_Init 或调用SDL_InitSubSystem(SDL_INIT_JOYSTICK); 来初始化操纵杆子系统
    • 检查SDL_NumJoysticks() &gt; 0
    • 获取操纵杆0:joystick = SDL_JoystickOpen(0);
    • 启用事件:SDL_JoystickEventState(SDL_ENABLE);
    • 使用SDL_PollEvent 处理您的事件
    • 在程序结束时,关闭游戏杆:SDL_JoystickClose(joystick);

    此外,请确保在 Windows 中正确检测到操纵杆并正确报告其输入。

    【讨论】:

      【解决方案4】:

      看起来您的 SDL 初始化不正确。

      替换

      SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK)
      

      SDL_Init(SDL_INIT_EVERYTHING)
      

      【讨论】:

        【解决方案5】:

        这是 SDL 1.2 还是 2.0?就我而言,2.0 SDL_PollEvent(&event) 实际上并没有在事件结构中放入任何数据。在那次通话之后,我不得不使用 SDL_JoystickGetAxis(joystick_id, axis) 和朋友来获取数据。

        因此,在您的情况下,请尝试将 SDL_JoystickGetAxis 调用移出事件类型的 if-test。

        【讨论】:

          【解决方案6】:

          如果您调用SDL_NumJoysticks 来获取连接的控制器数量,然后调用SDL_JoystickOpen,它会在您的游戏循环之前返回一个操纵杆标识符,那么您将收到SDL_JOYAXISMOTION 事件。

          例如

          int num_joy;
          num_joy = SDL_NumJoysticks();
          printf("%d joysticks found\n", num_joy);
          for(int i = 0; i < num_joy; i++)
          {
              SDL_Joystick *joystick = SDL_JoystickOpen(i);
              printf("Joystick name: %s\n", SDL_JoystickName(joystick));
          }
          
          SDL_Event event;
          bool quit = false;
          // Game loop
          while(!quit)
          {
              // event loop
              while(SDL_PollEvent(&event))
              {
                  if (event.type == SDL_JOYAXISMOTION)
                  {
                      printf("Joystick______EVENT!\n");
                  }
                  // etc.....
                  
          

          https://wiki.libsdl.org/SDL_JoystickName

          【讨论】:

            【解决方案7】:

            我不知道这对你有什么帮助,但我知道 pygame 支持游戏杆。 pygame 是 SDL 库的 python 端口。如果一切都失败了,我想你总是可以在 python 中编写那段特定的代码。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2018-12-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多