Sol's Graphics for Beginners

(ch10.cpp)

(prebuilt win32 exe)

10 - Joystick Support

(Last revised 9. August 2005)

Feel free to make a copy of the project, or continue from the last one.

Analog joystick support using SDL is pretty simple, so let's add it just for kicks.

One new variable (add near beginning of the file):

// Pointer to the joystick interface
SDL_Joystick *gJoystick = NULL;

We'll use this pointer to access the joystick, if one is available.

Add the following lines in the init() function:

if (SDL_NumJoysticks() > 0)
{
  gJoystick = SDL_JoystickOpen(0);		
  if (SDL_JoystickNumAxes(gJoystick) < 2)
  {
    // Not enough axes for our use; don't use the joystick.
    SDL_JoystickClose(gJoystick);
    gJoystick = NULL;
  }
}

Here we first ask SDL how many joysticks are available. If the answer is more than 0, we open the first available joystick. Then, we ask how many axes the joystick has; if the result is below 2, we close the joystick and give up.

Some dancemats may exist as just a bunch of buttons. Generally speaking any other kind of joystick should have at least X and Y axis.

Under windows, the above code will open the 'preferred' joystick for the system. It is possible that a system has several joysticks. If your joystick doesn't seem to work, try checking whether it is selected as the 'preferred' joystick.

In a complete game, it would be nice to let the user decide whether to use a joystick or not, and which one, if several joysticks are connected.

Next, we'll read the joystick. Add the following lines in our physics loop, before the slowdown lines:

if (gJoystick)
{
  gXMov += (SDL_JoystickGetAxis(gJoystick, 0) / 32768.0f) * THRUST;
  gYMov += (SDL_JoystickGetAxis(gJoystick, 1) / 32768.0f) * THRUST;
}

Since the axes are analog by default, we're dividing the range by 32768.0f to get the range to -1..1. Then we multiply that by our thrust value. This means that with an analog joystick, the player can move the ball very slowly if wanted.

Digital joysticks work just like analog ones, except that they can only report values -32768, 0 and 32768.

Note that the above does not override keyboard control at all: if you want to, you can move very fast by using both the joystick and the keyboard in the same direction. We could solve this by either capping the maximum speed, or by ignoring the joystick if some keyboard key is pressed. As it probably won't be a problem, we'll ignore this 'feature' for now.

We're not done yet, though. If you try to run the appliation at this point, the joystick opening will fail, since we haven't initialized the joystick subsystem of SDL. Before we do that, let's make sure the joystick gets closed, as well.

Add the following function after the init() function:

void deinit()
{
  if (gJoystick)
    SDL_JoystickClose(gJoystick);
}

This will, when called, close the joystick.

We only need to add a couple of things to the main() function before we're done. First, find the atexit(SDL_Quit) line and add the following after it:

// make sure our deinit gets called at shutdown.
atexit(deinit);

Since atexit functions are called in LIFO (last in, first out) order, our deinit will now be called before SDL_Quit, ensuring correct shutdown order. Lastly, change the beginning of the main() function to look like this:

// Initialize SDL's subsystems
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) 
{
  fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
  exit(1);
}

Apart from the comment change, the only change is the addition of the SDL_INIT_JOYSTICK in the SDL_Init() function. After this, you should be able to control the ball using joystick. If you don't have a joystick, don't worry - the cursor keys still work just fine, and the joystick will only be used if one is found.

Okay, enough with the controls!

The excitement will increase manyfold by 11 - Adding In the Level.

Having problems? Improvement ideas? Just want to discuss this tutorial? Try the forums!

Any comments etc. can be emailed to me.