Tricks of the Windows Game Programming Gurus:Uplinking with DirectInput and Force Feedback

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

Luckily, you only need to set the range of the X-Y axes (and maybe the dead zone) to make things work, so that’s all I’m going to show. If you’re interested in learning more, refer to the DirectX SDK on this subject. Nonetheless, the following code should get you started on setting other properties if you need to. The structure you need to set up is as follows:

    typedef struct DIPROPRANGE

            {

            DIPROPHEADER diph;

            LONG         lMin;

            LONG         lMax;

            } DIPROPRANGE, *LPDIPROPRANGE;

This has another nested structure, `DIPROPHEADER`:

    typedef struct DIPROPHEADER

            {

            DWORD    dwSize;

            DWORD    dwHeaderSize;

            DWORD    dwObj;

            DWORD    dwHow;

            } DIPROPHEADER, *LPDIPROPHEADER;

And both of them have a billion ways of being set up, so please look at the DirectX SDK if you’re interested. It would take 10 more pages just to list all the various flags you can send! Anyway, here’s the code to set the axes ranges:

    // this structure holds the data for the property changes

    DIPROPRANGE joy_axis_range;

    // first set x axis tp -1024 to 1024

    joy_axis_range.lMin = -1024;

    joy_axis_range.lMax = 1024;

    joy_axis_range.diph.dwSize       = sizeof(DIPROPRANGE);

    joy_axis_range.diph.dwHeaderSize = sizeof(DIPROPHEADER);

    // this holds the object you want to change

    joy_axis_range.diph.dwObj = DIJOFS_X;

    // above can be any of the following:

    //DIJOFS_BUTTON(n) - for buttons buttons

    //DIJOFS_POV(n) - for point-of-view indicators.

    //DIJOFS_RX - for x-axis rotation.

    //DIJOFS_RY - for y-axis rotation.

    //DIJOFS_RZ - for z-axis rotation (rudder).

    //DIJOFS_X - for x-axis.

    //DIJOFS_Y - for y-axis.

    //DIJOFS_Z - for the z-axis.

    //DIJOFS_SLIDER(n) - for any of the sliders.

    // object access method, use this way always

    joy_axis_range.diph.dwHow = DIPH_BYOFFSET;

    // finally set the property

    lpdijoy->SetProperty(DIPROP_RANGE,&joy_axis_range.diph);

    // now y-axis

    joy_axis_range.lMin = -1024;

    joy_axis_range.lMax = 1024;

    joy_axis_range.diph.dwSize       = sizeof(DIPROPRANGE);

    joy_axis_range.diph.dwHeaderSize = sizeof(DIPROPHEADER);

    joy_axis_range.diph.dwObj        = DIJOFS_Y;

    joy_axis_range.diph.dwHow        = DIPH_BYOFFSET;

    // finally set the property

    lpdijoy->SetProperty(DIPROP_RANGE,&joy_axis_range.diph);

At this point, the joystick would have the X and Y axes set to a range of -1024 to 1024. This range is arbitrary, but I like it. Notice that you use a data structure called `DIPROPRANGE`. This is the structure that you set up to do your bidding. The bad thing about it is that there are a million ways to set up the structure, so it’s a real pain.

However, using the previous template, you can at least set the range of any axis—just change the `joy_axis_range.diph.dwObj` and `joy_axis_range.diph.dwHow` fields to whatever you need.

As a second example of setting properties, let’s set the dead zone (or dead band) of the X and Y axes. The dead zone is the amount of neutral area in the center of the stick. You might want the stick to be able to move a bit away from the center and not send any values. This is shown in Figure 9.12.

Figure 9.12 The mechanics of the joystick dead zone.

> Warning: The dead zone is always in terms of 0-10000 or hundreds of a percent. If you want a dead zone of 50%, use 5000, for 10% use 1000, and so forth.

For example, in the previous example you set the X and Y axis range to -1024 to 1024, so if you wanted a 10 percent dead zone on both axes, you would set it for about 102 units in both the + and - directions, right? Wrong!!! The dead zone is in terms of an absolute range of 0-10,000, no matter what range you set the joystick to. Thus, you have to compute 10 percent of 10,000 rather than 1024—10% × 10000 = 1000. This is the number you need to use.

Because this operation is a little simpler, you need only use the `DIPROPWORD` structure:

    typedef struct DIPROPDWORD

            {

            DIPROPHEADER     diph;

            DWORD            dwData;

            } DIPROPDWORD, *LPDIPROPDWORD;

This is much simpler than the `DIPROPRANGE` structure used in the previous example. Here’s how to do it:

    DIPROPDWORD dead_band; // here’s our property word

    dead_band.diph.dwSize       = sizeof(dead_band);

    dead_band.diph.dwHeaderSize = sizeof(dead_band.diph);

    dead_band.diph.dwObj        = DIJOFS_X;

    dead_band.diph.dwHow        = DIPH_BYOFFSET;

    // 100 will be used on both sides of the range +/-

    dead_band.dwData            = 1000;

    // finally set the property

    lpdijoy->SetProperty(DIPROP_DEADZONE,&dead_band.diph);

    And now for the Y-axis:

    dead_band.diph.dwSize       = sizeof(dead_band);

    dead_band.diph.dwHeaderSize = sizeof(dead_band.diph);

    dead_band.diph.dwObj        = DIJOFS_Y;

    dead_band.diph.dwHow        = DIPH_BYOFFSET;

    // 100 will be used on both sides of the range +/-

    dead_band.dwData            = 1000;

    // finally set the property

    lpdijoy->SetProperty(DIPROP_DEADZONE,&dead_band.diph);

And that’s all there is to that. Thank Zeus!

Acquiring the Joystick

Now, let’s acquire the joystick with a call to `Acquire()`:

    // acquire the joystick

    if (FAILED(lpdijoy->Acquire()))

       { /* error */ }

Of course, remember to `Unacquire()` the joystick when you’re through with it, right before calling `Release()` on the interface to release the device itself.

Polling the Joystick

Joysticks are the only devices that need polling (so far). The reason for polling is the following: Some joystick drivers generate interrupts, and the data is always fresh. Some drivers are less intelligent (or more efficient) and must be polled. Whatever the philosophical viewpoint of the driver developer, you must always call `Poll()` on the joystick before trying to read the data. Here’s the code for doing so:

    If (FAILED(lpdijoy->Poll()))

       { /* error */ }

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.