Joysticks
Last Updated 12/28/09
Here we'll learn to use get input from a joystick/gamepad. This program is basically the motion tutorial, only this time a joystick will move around the dot instead of the keyboard.A Game pads and joysticks tutorial with SDL 2 is now available.
//The joystick that will be used
SDL_Joystick *stick = NULL;
Joysticks have their own data type in SDL which is SDL_Joystick.
In this program we declare our joystick as a global variable.
In this program we declare our joystick as a global variable.
//The dot
class Dot
{
private:
//The offsets of the dot
int x, y;
//The velocity of the dot
int xVel, yVel;
public:
//Initializes
Dot();
//Handles joystick
void handle_input();
//Moves the dot
void move();
//Shows the dot
void show();
};
As you can see, the Dot class has pretty much stayed the same.
The only thing that has changed is how we handle the input.
bool init()
{
//Initialize all SDL subsystems
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
return false;
}
//Set up the screen
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
//If there was an error in setting up the screen
if( screen == NULL )
{
return false;
}
//Check if there's any joysticks
if( SDL_NumJoysticks() < 1 )
{
return false;
}
//Open the joystick
stick = SDL_JoystickOpen( 0 );
//If there's a problem opening the joystick
if( stick == NULL )
{
return false;
}
//Set the window caption
SDL_WM_SetCaption( "Move the Dot", NULL );
//If everything initialized fine
return true;
}
A key difference between using keys for input and using joysticks is that joysticks have to be initialized.
In the initialization function we use SDL_NumJoysticks() to check how many joysticks are plugged in. If at least 1 joystick is plugged in, we open the first joystick available using SDL_JoystickOpen(). The first available joystick is joystick 0 since in programming we always start counting at 0. When there's problem in opening the joystick, SDL_JoystickOpen() returns NULL.
In the initialization function we use SDL_NumJoysticks() to check how many joysticks are plugged in. If at least 1 joystick is plugged in, we open the first joystick available using SDL_JoystickOpen(). The first available joystick is joystick 0 since in programming we always start counting at 0. When there's problem in opening the joystick, SDL_JoystickOpen() returns NULL.
void clean_up()
{
//Free the surface
SDL_FreeSurface( dot );
//Close the joystick
SDL_JoystickClose( stick );
//Quit SDL
SDL_Quit();
}
In the clean up function, we have to call SDL_JoystickClose() to close the joystick that was opened.
void Dot::handle_input()
{
//If a axis was changed
if( event.type == SDL_JOYAXISMOTION )
{
//If joystick 0 has moved
if( event.jaxis.which == 0 )
{
//If the X axis changed
if( event.jaxis.axis == 0 )
{
//If the X axis is neutral
if( ( event.jaxis.value > -8000 ) && ( event.jaxis.value < 8000 ) )
{
xVel = 0;
}
//If not
else
{
//Adjust the velocity
if( event.jaxis.value < 0 )
{
xVel = -DOT_WIDTH / 2;
}
else
{
xVel = DOT_WIDTH / 2;
}
}
}
When a joystick moves, a SDL_JOYAXISMOTION occurs.
First we check if the joystick that has moved is joystick 0. It's kind of pointless in this program since the only initialized joystick is joystick 0, but in real games you'll need to check multiple joysticks.
Then we check which axis it has moved on. On most modern joysticks, the X axis is 0, and the Y axis is 1.
After that we check if the joystick X value is between -8000, and 8000. If it is, it's neutral and the dot stays still.
You may be thinking "how the hell is such a large range considered neutral?". The thing is a joystick's axis have a range of -32768 to 32767. You could have the joystick at 0 and if you sneezed on it, it would be at like 200.
If the joystick is not in the neutral range, we set the X velocity accordingly.
First we check if the joystick that has moved is joystick 0. It's kind of pointless in this program since the only initialized joystick is joystick 0, but in real games you'll need to check multiple joysticks.
Then we check which axis it has moved on. On most modern joysticks, the X axis is 0, and the Y axis is 1.
After that we check if the joystick X value is between -8000, and 8000. If it is, it's neutral and the dot stays still.
You may be thinking "how the hell is such a large range considered neutral?". The thing is a joystick's axis have a range of -32768 to 32767. You could have the joystick at 0 and if you sneezed on it, it would be at like 200.
If the joystick is not in the neutral range, we set the X velocity accordingly.
//If the Y axis changed
else if( event.jaxis.axis == 1 )
{
//If the Y axis is neutral
if( ( event.jaxis.value > -8000 ) && ( event.jaxis.value < 8000 ) )
{
yVel = 0;
}
//If not
else
{
//Adjust the velocity
if( event.jaxis.value < 0 )
{
yVel = -DOT_HEIGHT / 2;
}
else
{
yVel = DOT_HEIGHT / 2;
}
}
}
}
}
}
Then pretty much the same thing is done to the Y axis.
Handling SDL_JoyAxisEvent is the hardest event to handle when dealing with joysticks. Handling other events like SDL_JoyBallEvent, SDL_JoyHatEvent, and SDL_JoyButtonEvent should be easy to figure out with a quick look at the SDL API documentation.
Handling SDL_JoyAxisEvent is the hardest event to handle when dealing with joysticks. Handling other events like SDL_JoyBallEvent, SDL_JoyHatEvent, and SDL_JoyButtonEvent should be easy to figure out with a quick look at the SDL API documentation.