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

Once you set the data format to one of these types, DirectInput will send each data packet back in a certain format. DirectInput again has some predefined formats to make this easy, as shown in Table 9.3.

Table 9.3 DirectInput Data Structures Used to Send Data When Using Generic Data Formats

Name | Description
--- | ---

`DIMOUSESTATE` | This data structure holds a mouse message.
`DIJOYSTATE` | This data structure holds a standard joystick-like device message.
`DIJOYSTATE2` | This data structure holds a standard force feedback device message.

I’ll show you the actual structures when we get to the mouse and the joystick. However, you’re probably wondering where the damn keyboard structure is. Well, it’s so simple that there isn’t a type for it. It’s nothing more than an array of 256 bytes, each representing one key, thus making the keyboard look like a set of 101 momentary switches.

If DirectX is missing something and I want to create a “DirectXish” version of it, I will usually create the missing data structure or function, but with a leading underscore to remind me six months from now that I invented it.

Hence, using the default DirectInput data format and data type is very similar to using the Win32 function `GetAsyncKeyState()`. In any case, all you need is a type like this:

    typedef _DIKEYSTATE UCHAR[256];

So with all that in mind, let’s set the data format for the poor little keyboard:

    // set data format

    if (FAILED(lpdikey->SetDataFormat(&c_dfDIKeyboard)))

       { /* error */ }

Notice that I used the & operator to get the address of the global `c_dfDIKeyboard` because the function wants a pointer to it.

Acquiring the Keyboard

You’re getting there! Almost done. You’ve created the DirectInput main COM object, created a device, set the cooperation level, and set the data format. The next step is to acquire the device from DirectInput. To do this, use the function method `IDIRECTINPUTDEVICE::Acquire()` with no parameters. Here’s an example:

    // acquire the keyboard

    if (FAILED(lpdikey->Acquire()))

       { /* error */ }

And that’s all there is to it. Now you’re ready to get input from the device! It’s time to celebrate. I think I’ll have a Power Bar. :)

Retrieving Data from the Keyboard

Retrieving data from all devices is mostly the same, plus or minus a couple of details that may be device-specific. In general, you must do the following:

> Tip: Remember, any method you can call with a `IDIRECTINPUTDEVICE` interface can be called with a `IDIRECTINPUTDEVICE2` interface.

  1. (Optional) Poll the device for `IDIRECTINPUTDEVICE2` devices like joysticks.
  2. Read the immediate data from the device with a call to `IDIRECTINPUTDEVICE::GetDeviceState()` or `IDIRECTINPUTDEVICE2::GetDeviceState()`.

Here’s what the `GetDeviceState()` function looks like:

    HRESULT GetDeviceState(

       DWORD cbData,    // size of state data structure

       LPVOID lpvData); // ptr to memory to receive data

The first parameter is the size of the receiving data structure that the data will be stuffed into: 256 for keyboard data, `sizeof(DIMOUSESTATE)` for the mouse, `sizeof(DIJOYSTATE)` for the plain joystick, and so on. The second parameter is just a pointer to where you want the data to be stored. Hence, here’s how you might read the keyboard:

    // here's our little helper typedef

    typedef _DIKEYSTATE UCHAR[256];

    _DIKEYSTATE keystate[256]; // this will hold the keyboard data

Now let’s read the keyboard:

    if (FAILED(lpdikey->GetDeviceState(sizeof(_DIKEYSTATE),

             (LPVOID)keystate)))

           { /* error */ }

Of course, you would do this once for each game loop at the top of the loop, before any processing has occurred.

Once you have the data, you’ll want to test for keypresses, right? Just as there are constants for the `GetAsyncKeyState()` function, there are constants for the keyboard switches that resolve to their positions in the array. They all start with `DIK_` (DirectInput key, I would imagine) and are defined in `DINPUT.H`. Table 9.4 contains a partial list of them (please refer to the DirectX SDK docs for the complete list).

Table 9.4 The DirectInput Keyboard State Constants

Symbol | Description
--- | ---

`DIK_ESCAPE` | The Esc key
`DIK_0-9` | Main keyboard 0 through 9
`DIK_MINUS` | Minus key
`DIK_EQUALS` | Equals key
`DIK_BACK` | Backspace key
`DIK_TAB` | Tab key
`DIK_A-Z` | Letters A through Z
`DIK_LBRACKET` | Left bracket
`DIK_RBRACKET` | Right bracket
`DIK_RETURN` | Return/Enter on main keyboard
`DIK_LCONTROL` | Left control
`DIK_LSHIFT` | Left shift
`DIK_RSHIFT` | Right shift
`DIK_LMENU` | Left Alt
`DIK_SPACE` | Spacebar
`DIK_F1-15` | Function keys 1 through 15
`DIK_NUMPAD0-9` | Numeric keypad keys 0 through 9
`DIK_ADD` | + on numeric keypad
`DIK_NUMPADENTER` | Enter on numeric keypad
`DIK_RCONTROL` | Right control
`DIK_RMENU` | Right Alt
`DIK_HOME` | Home on arrow keypad
`DIK_UP` | Up arrow on arrow keypad
`DIK_PRIOR` | PgUp on arrow keypad
`DIK_LEFT` | Left arrow on arrow keypad
`DIK_RIGHT` | Right arrow on arrow keypad
`DIK_END` | End on arrow keypad
`DIK_DOWN` | Down arrow on arrow keypad
`DIK_NEXT` | PgDn on arrow keypad
`DIK_INSERT` | Insert on arrow keypad
`DIK_DELETE` | Delete on arrow keypad

Bolded entries simply mean to follow the sequence. For example, `DIK_0-9` means that there are constants `DIK_0`, `DIK_1`, `DIK_2`, and so forth.

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.