user2014680
user2014680

Reputation: 19

Joystick won't work using SDL

I'm building a simple game in SDL. I've been through countless tutorials and I've clearly missed something as it still ignoring my Joystick completely

In my constructor

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

In my update I'm calling a test to check I have actually initialized the joystick

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

Here is my player update as well

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 is simply a bool which once true will mean my enemies start spawning. I also run a check in main

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

When I run the game it loads as normal but no matter how much I move the joystick it won't set test to true.

I also tried using the following in the while poll event loop instead.

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

Any idea's what I have missed?

Upvotes: 1

Views: 6870

Answers (7)

Joe Gasewicz
Joe Gasewicz

Reputation: 1485

If you call SDL_NumJoysticks to get the number of controllers connected, then call SDL_JoystickOpen which returns a joystick identifier before your game loop then you will receive the SDL_JOYAXISMOTION events.

e.g.

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.....
        

See https://wiki.libsdl.org/SDL_JoystickName

Upvotes: 0

SourceNut
SourceNut

Reputation: 31

I found a weird behaviour in SDL2:

If no events are put into the queue, try adding the following before the SDL_Init call:

SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,"1");

Upvotes: 3

larslars
larslars

Reputation: 168

Is this SDL 1.2 or 2.0? In my case, on 2.0 SDL_PollEvent(&event) didn't actually put any data in the event struct. After that call, I had to use SDL_JoystickGetAxis(joystick_id, axis) and friends to get data.

So in your case, try to move the SDL_JoystickGetAxis call out of the if-test on event-type.

Upvotes: 0

user2183530
user2183530

Reputation:

Looks like your SDL isn't init proper.

replace

SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK)

with

SDL_Init(SDL_INIT_EVERYTHING)

Upvotes: 1

Raptor007
Raptor007

Reputation: 398

I think emartel has the best answer to make sure SDL_joystick is working.

When does World::playerMovement() happen? The overall flow of your program is hard to determine from these snippets.

I'm happy to share with you my code for handling joysticks, which keeps track of: multiple joysticks, axes scaled [-1,1] with deadzone removed, and buttons held down.

And here's a snippet of how that would be utilized as part of your main loop:

// 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.
}

Upvotes: 2

emartel
emartel

Reputation: 7773

Are you sure joystick points to a valid joystick?

You state that you're getting it in your Constructor... does that contructor happen to be called before you initialize SDL with SDL_INIT_JOYSTICK? This could happen if your player is a global variable.

Make sure that in order you:

  • Init the Joystick subsystem, either by adding it to your SDL_Init with | SDL_INIT_JOYSTICK or by calling SDL_InitSubSystem(SDL_INIT_JOYSTICK);
  • Check SDL_NumJoysticks() > 0
  • Get joystick 0: joystick = SDL_JoystickOpen(0);
  • Enable events: SDL_JoystickEventState(SDL_ENABLE);
  • Process your events with SDL_PollEvent
  • At the end of your program, close your joystick: SDL_JoystickClose(joystick);

Also, make sure the joystick is properly detected in Windows and reports its inputs properly.

Upvotes: 1

Kevin Martin Jose
Kevin Martin Jose

Reputation: 640

I do not know how this can help you, but I do know that pygame supports joystick. And pygame is the python port of the SDL library. If everything fails, I guess you can always write that particular piece of code in python.

Upvotes: -1

Related Questions