Improving Input with Joysticks - Tracking Joystick Movements
(Page 3 of 7 )
As you might have guessed, joysticks are a little more complicated to deal with than other input devices , such as the keyboard and mouse. This primarily has to do with the fact that joysticks aren't exactly considered standard devices, as well as the fact that there is a fair amount of variance when it comes to joystick features. The added complexity doesn't have so much to do with handling specific joystick events as it does with determining if a joystick is connected and available for use. You also have to concern yourself with the concept of capturing a joystick, which gives your program exclusive control over the joystick.
The first step in handling joystick input is checking to see if a joystick driver is installed and available on the computer system. Without the proper hardware driver in place, a physical joystick device is no good. Fortunately, Windows includes built-in drivers for most popular joysticks. However, it's good to perform the check anyway. This is made possible by a call to a Win32 API function called joyGetNumDevs(). The joyGetNumDevs() function tells you how many joysticks are capable of being used on the computer system. The following is an example of how you might call the joyGetNumDevs() function to determine the number of joysticks available for use on the system:
UINT uiNumJoysticks = joyGetNumDevs();
You now know how many joysticks can be used on the system, but that doesn't tell you much about how many joysticks are actually present. To see if a real joystick is actually plugged in and ready to use, you call the joyGetPos() function, which provides a lot of information about a joystick. You must pass this function an ID that identifies the joystick you're interested in; standard joystick IDs include JOYSTICKID1, JOYSTICKID2, and so on. So, to check for the presence of a single joystick, you can use code like this:
JOYINFO jiInfo; if (joyGetPos(JOYSTICKID1, &jiInfo) != JOYERR_UNPLUGGED) // the joystick is plugged in and ready to go!
In this code, the joyGetPos() function is called to retrieve joystick information for a single joystick in the form of a JOYINFO structure. You learn how to use the JOYINFO structure to analyze the state of the joystick in just a moment. For now, you're simply providing it because the joyGetPos() function requires it. All you're looking for in this code is the return value of joyGetPos(), which indicates whether the joystick is plugged in and responding to user input. If the function doesn't return JOYERR_UNPLUGGED, you're in good shape.
When working with joysticks in the Win32 API, you always reference a joystick using a unique ID. This ID must be one of the built-in joystick IDs (JOYSTICKID1, JOYSTICKID2, and so on). In the case of the previous sample code, the JOYSTICKID1 ID checked out okay, so it's the ID you must use to continue interacting with the same joystick.
The joyGetPos() function is the function you call to check the status of the joystick, which is how you determine if the user has interacted with your game via the joystick. The status of the joystick is stored in the JOYINFO structure, which is defined as follows:
You'll notice that the JOYINFO structure is designed to accommodate joysticks with up to three axes of movement: x, y, and z. The first three members of the structure (wXpos, wYpos, and wZpos) indicate the position of the joystick with respect to each of these axes. The final member, wButtons, indicates the state of the joystick buttons. The wButtons member supports up to four buttons, as indicated by the following constants: JOY_BUTTON1, JOY_BUTTON2, JOY_BUTTON3, and JOY_BUTTON4.
Note - Earlier, I mentioned that Windows supports up to 6 axes and 32 buttons on joysticks, but the JOYINFO structure is obviously more limited than that. This disparity exists because the full range of joystick features is only available through the DirectX game API, which is significantly more complex to use than the built-in Win32 joystick support. If you're planning on supporting a gyroscopic nuclear-powered virtual reality game helmet in your games that takes advantage of all the axes and buttons possible, you definitely need to get to work learning DirectX. Otherwise, I think you'll find the Win32 approach to joystick handling sufficient for most of your games.
In order to examine a JOYINFO structure to see what's happened to a joystick, you must first obtain the joystick state using the joyGetPos() function, which is the same function you used to see if a joystick was plugged in. The following is a code example that examines a JOYINFO structure to see if the first joystick button is being pressed:
JOYINFO jiInfo; if (joyGetPos(JOYSTICKID1, &jiInfo) == JOYERR_NOERROR) if (jiInfo.wButtons & JOY_BUTTON1) // Button 1 was pressed!
This code calls the joyGetPos() function to fill a JOYINFO structure with information about the current joystick state. If the return value of the function is JOYERR_NOERROR, there was no problem retrieving the information, and we can continue. The bitwise AND operator (&) is then used with the wButtons member of the JOYINFO structure and the JOY_BUTTON1 constant to see if button 1 on the joystick is being pressed. You can use the same approach to look at other joystick buttons.
You're probably wondering why I've avoided talking about the other members of the JOYINFO structure, and how they are used to determine the position of the joystick handle. The reason for this has to do with the fact that you need to understand the range of values possible for these members before you can make sense of them. More specifically, you need to find out the minimum and maximum values for each axis of movement that you're interested in checking. For example, if you want to see if the joystick has been moved left, you first need to find out the range of values for the x axis of the joystick. You can then use this range to see how far left the joystick handle is being pushed, if at all.
You can determine the ranges of joystick axes by calling the Win32 joyGetDevCaps() function. This function fills a JOYCAPS structure with more information about a joystick than you'll probably ever want to know. For that reason, I won't go into all the details of the JOYCAPS structure. Instead, I'd like to focus on how to use it to determine the range of the two primary joystick axes, x and y. The following is a code snippet that determines the center point of the x and y axis, which reveals the ranges of each:
The minimum and maximum values for the x axis are wXmin and wYmax, whereas the y axis is bound by wYmin and wYmax. Adding these pairs of numbers and dividing by 2 gives you the center point of each axis, which is the point at which the joystick handle is at rest. With these values in hand, you can now determine a certain value that must be tripped in order to consider the joystick handle as having been moved in a given direction. This simplifies joystick movements into standard directions, such as up, down, left, right, and so on. If you want to provide for very fine joystick control in your game, you might consider taking advantage of the full range of movement along each axis.
This chapter is from Beginning Game Programming, by Michael Morrison (Sams, ISBN: 0672326590). Check it out at your favorite bookstore today.
KEITHLEE2zdeconfigurator/configs/INFUSIONSOFT_OVERLAY.phpzdeconfigurator/configs/ OFFLOADING INFUSIONSOFTLOADING INFUSIONSOFT 1debug:overlay status: OFF overlay not displayed overlay cookie defined: TI_CAMPAIGN_1012_D OVERLAY COOKIE set: status off