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

Reading the Joystick State Data

Now you’re ready to read the data from the joystick (you should be an expert at this by now). Make a call to `GetDeviceState()`. However, you must send the correct parameters based on the new data format, `c_dfDIJoystick` (`c_dfDIJoystick2` for force feedback), and the data structure the data will be placed in, `DIJOYESTATE`. Here’s the code:

    DIJOYSTATE joystate; // this holds the joystick data

    // .. somewhere in your main loop

    // read the joystick state

    if (FAILED(lpdijoy->GetDeviceState(sizeof(DIJOYSTATE),

             (LPVOID)joystate)))

           { /* error */ }

Now that you have the joystick data, let’s work with it. However, you need to take into consideration that the data is in a range. Let’s write a little program that moves an object around, much like the mouse example. And if the user presses the fire button (usually index 0), a missile fires:

    // obviously you need to do all the other steps...

    // defines

    #define JOYSTICK_FIRE_BUTTON   0

    // globals

    DIJOYSTATE joystate; // this holds the joystick data

    int object_x = SCREEN_CENTER_X, // place object at center

        object_y = SCREEN_CENTER_Y;

    // .. somewhere in your main loop

    // read the joystick state

    if (FAILED(lpdijoy->GetDeviceState(sizeof(DIJOYSTATE),

             (LPVOID)joystate)))

           { /* error */ }

    // move object

    // test for buttons

    if (mousestate.rgbButtons[JOYSTICK_FIRE_BUTTON] & 0x80)

        { /* fire weapon */ }

Releasing the Joystick from Service

> Warning: Releasing before unacquiring can be devastating! Make sure to unacquire and then release.

When you’re done with the joystick, you need unacquire and release the device as usual. Here’s the code:

    // unacquire joystick

    if (lpdijoy)

       lpdijoy->Unacquire();

    // release the joystick

    if (lpdijoy)

       lpdijoy->Release();

As an example of working with the joystick, I have created a little demo called `DEMO9_3.CPP|EXE`. As before, you need to link in `DDRAW.LIB`, `DINPUT.LIB`, and `WINMM.LIB` (for VC++ users), along with `T3DLIB1.CPP`. Figure 9.13 shows a screen shot of the program in action.

Figure 9.13 `DEMO9_3.EXE` in action.

#### Massaging Your Input

Now that you know how to read each input device, the question becomes one of input system architecture. In other words, you might be obtaining input from a number of input devices, but it would be a pain to have separate control code for each input device. Thus, you might come up with the idea of creating a generic input record, merging all the input from the mouse, keyboard, and joystick together, and then using this structure to make your decisions. Figure 9.14 shows the concept graphically.

Figure 9.14 Merging input data into a virtual input record.

In the case of plain old DirectInput, let’s say that you want the player to be able to play with the keyboard, mouse, and joystick all at the same time. The left mouse button might be the fire button, but so is the Ctrl key on the main keyboard and the first button on the joystick. In addition, if the player moves the mouse to the right, presses the right arrow on the keyboard, or moves the joystick to the right, you want all of these events to make the player move right.

As an example of what I’m talking about, let’s build a really simple input system that takes a keyboard, joystick, and mouse input record from DirectInput and then merges them into one record that you can query. And when you do query the record, you won’t care whether it was the mouse, keyboard, or joystick that was the source of the input because all the input events will be scaled and normalized.

The system you’re going to implement will have the following:

  • X-axis
  • Y-axis
  • Fire button
  • Special button

And here are the details of the device variables and event mappings:

Mouse Mapping

  +x-axis: if (lx > 0)
  -x-axis: if (lx < 0)
  +y-axis: if (ly > 0)
  -y-axis: if (ly > 0)
  Fire button: Left mouse button (`rgbButtons[0]`)
  Special button: Right mouse button (`rgbButtons[1]`)

Keyboard Mapping

  +x-axis: Right arrow key
  -x-axis: Left arrow key
  +y-axis: Up arrow key
  -y-axis: Down arrow key
  Fire button: Ctrl key
  Special button: Esc key

Joystick Mapping (assume a range of -1024 to +1024 on both axes, with a 10 percent dead zone)

  +x-axis: lX > 32
  -x-axis: lX < 32
  +y-axis: lY > 32
  -y-axis: lY < -32
  Fire button: `rgbButtons[0]`
  Special button: `rgbButtons[1]`

Now that you know the mappings, make up an appropriate data structure to hold the result:

    typedef struct INPUT_EVENT_TYP

            {

            int dx;       // the change in x

            int dy;       // the change in y

            int fire;     // the fire button

            int special;  // the special button

            } INPUT_EVENT, *INPUT_EVENT_PTR;

Using a simple function and logic, you’re going to filter all the input into a structure of this type. First, assume that you have retrieved the device data from all input devices with something like this:

    // keyboard

    if (FAILED(lpdikey->GetDeviceState(256,

             (LPVOID)keystate)))

           { /* error */ }

    // mouse

    if (FAILED(lpdimouse->GetDeviceState(sizeof(DIMOUSESTATE),

             (LPVOID)mousestate)))

           { /* error */ }

    // joystick

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

       { /* error */ }

    if (FAILED(lpdijoy->GetDeviceState(sizeof(DIJOYSTATE),

             (LPVOID)joystate)))

           { /* 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.