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

To test if any key is down, you must test the 0x80 bit in the 8-bit byte of the key in question; in other words, the uppermost bit. For example, you’d use the following if you wanted to test whether the Esc key was pressed:

> Tip: You could probably get away without the & and the bit test, but Microsoft doesn’t guarantee that other bits won’t be high even if the key isn’t down. It’s a good idea to do the bit test just to be safe.

    if (keystate[DIK_ESCAPE] & 0x80)

        { // it's pressed */ }

    else

        { /* it's not */ }

The `and` operator is a bit ugly; you can make it look better with a macro like this:

    #define DIKEYDOWN(data,n) (data[n] & 0x80)

Then you can just write this:

    if (DIKEYDOWN(keystate, DIK_ESCAPE))

        { /* do it to it baby! */ }

Much cleaner, huh? And of course, when you’re done with the keyboard, you must “unacquire” it with `Unacquire()` and release it (along with the main DirectInput COM object) like this:

    // unacquire keyboard

    if (lpdikey)

       lpdikey->Unacquire();

    // release all devices

    if (lpdikey)

       lpdikey->Release();

    // .. more device unacquire/releases, joystick, mouse etc.

    // now release main COM object

    if (lpdi)

       lpdi->Release();

This is the first time that I’ve talked about the function `Unacquire()`, but it is so closely tied to releasing the object that I thought it appropriate for use here. However, if you simply want to unacquire a device but not release it, you can surely call `Unacquire()` on a device and reacquire it later. You might want to do this if you want another application to have access to the device when you aren’t using it.

> Warning: Of course, if you want to release the keyboard but keep the joystick (or some other combination), don’t release the main COM object until you’re completely ready to kill DirectInput.

For an example of using the keyboard, take a look at `DEMO9_1.CPP|EXE` on the CD. Figure 9.5 shows a screen shot of the action. The program uses all the techniques we have covered to set up the keyboard, and it lets you move a character around. To compile the program, remember to include `DDRAW.LIB`, `DINPUT.LIB`, and `WINMM.LIB` for VC++ users. Also, if you look at the header section of the program, you’ll notice that it uses `T3DLIB1.H`. Thus, it obviously needs `T3DLIB1.CPP` in the project to compile. By the end of the chapter, you will create an entire input library (which I have already completed and named `T3DLIB2.CPP|H`, but I’ll show that to you later in the chapter).

Figure 9.5 DEMO9_1.EXE in action.

#### Problem During Reading: Reacquisition

I hate to talk about problems that can occur with DirectX because there are so many of them. They aren’t bugs, but simply manifestations of running in a cooperative OS like Windows. One such problem that can occur with DirectInput is due to a device getting yanked from you or acquired by another application.

In this case, it’s possible that you had the device during the last frame of animation, and now it’s gone. Alas, you must detect this and be able to reacquire the device. Luckily, there is a way to test for it that is fairly simple. When you read a device, you test to see if it was acquired by another application. If so, you simply reacquire it and try reading the data again. You can tell because the `GetDeviceState()` function will return an error code.

The real error codes that `GetDeviceState()` returns are shown in Table 9.5.

Table 9.5 Error Codes for `GetDeviceState()`

Value | Description
--- | ---

`DIERR_INPUTLOST` | Device has lost input and will lose acquisition on next call.
`DIERR_INVALIDPARAM` | One of the parms to the function was invalid.
`DIERR_NOTACQUIRED` | You have totally lost the device.
`DIERR_NOTINITIALIZED` | The device is not ready.
`E_PENDING` | Data not yet available: chill.

So what you want to do is test for `DIERR_INPUTLOST` during a read and then try to reacquire if that error occurs. Here’s an example:

    HRESULT result; // general result

    while(result = lpdikey->GetDeviceState(

             sizeof(_DIKEYSTATE),

             (LPVOID)keystate) == DIERR_INPUTLOST)

         {

         // try an re-acquire the device

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

            {

            break; // serious error

            } // end if

> Tip: Although I’m showing you an example of reacquiring the keyboard, chances are this will never happen. In most cases, you will only lose joystick-like devices.

         } // end while

    // at this point, there is either a serious error or the data is valid

    if (FAILED(result))

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