Search Tips Advanced Search |
| Delphi Graphics and Game Programming Exposed with DirectX 7.0 by John Ayres Wordware Publishing, Inc. ISBN: 1556226373 Pub Date: 12/01/99
Search this book:
Previous | Table of Contents | Next
Listing 8-2: Enumerating device-specific effects
    var

      FDirectInput: IDirectInput;

      FDirectInputDevice: IDirectInputDevice2;

       .

       .

       .

    implementation

    uses DXTools, frmDevicesU;

       .

       .

       .

    function EnumEffects(var pdei: TDIEffectInfoA; pvRef: pointer) : Integer; stdcall;

    begin

      {filter out any effects that have adjustable type-specific parameters}

      if (pdei.dwStaticParams and DIEP_TYPESPECIFICPARAMS) =

          DIEP_TYPESPECIFICPARAMS then

      begin

        Result := 1;

        Exit;

      end;

      {add the name of the effect to the list box}

      frmJoyTestBed.lbxDevEffects.Items.Add(pdei.tszName);

      {continue enumeration}

      Result := 1;

    end;

    procedure TfrmEnumDevEffects.FormActivate(Sender: TObject);

    begin

       .

       .

       .

      {enumerate all hardware-specific effects}

      FDirectInputDevice.EnumEffects(EnumEffects, nil, DIEFT_HARDWARE);

    end;
Figure 8-6: Microsoft SideWinder Force Feedback Pro device effects Like all effects, you’ll use a TDIEffect structure when creating device-specific effects. However, some effects may have default values that will be used by the driver whenever certain specific members of the TDIEffect structure are set to a particular value. For example, the Microsoft SideWinder Force Feedback Pro joystick will use default values for the sample period and duration if the dwSamplePeriod and dwDuration members of the TDIEffect structure are set to 1000. Other devices will probably use different values, and may require delving into the driver documentation. Custom Forces If none of the standard effect types provide the tactile feedback sensation desired, you can attempt to create it using a custom force. A custom force is little more than an array of magnitudes. It replays this array of magnitudes as constant forces; each element is played in sequence at a constant interval and in the same direction (which can be reversed by negative magnitudes). Custom forces use the TDICustomForce structure for their type-specific parameters, which is defined as:
    TDICustomForce = packed record

      cChannels : DWORD;                      // number of channels

      dwSamplePeriod : DWORD;                 // sample period

      cSamples : DWORD;                       // number of elements in sample array

      rglForceData : ^longint;                // pointer to the array of samples

    end;
The cChannels member indicates how many axes are involved in the force, and results in each sample in the samples array being rotated amongst the axes (i.e., in the case of two axes and a cChannels setting of 2, element 1 applies to the first axis, element 2 to the second, element 3 to the first, etc.). This functionality may not be supported by all drivers. The dwSamplePeriod member is very similar to the dwSamplePeriod member of the TDIEffect structure. The dwSamplePeriod member of the TDICustomForce structure indicates how long each element in the samples array will play, whereas the dwSamplePeriod in the TDIEffect structure indicates how long DirectInput waits before recalculating the force output by the device. Most devices do not support the dwSamplePeriod member of the TDICustomForce structure, and instead use the dwSamplePeriod member of the TDIEffect structure to determine how long to play each sample. In most cases, both members should be set to the same value to avoid any confusing behavior. The cSamples member should be set to the number of elements in the array, which is pointed to by the rglForceData member. This array contains a series of longints that define the magnitudes in the range 10,000 to 10,000.
| Note: Applying an envelope to a custom force may not be supported by all drivers.
### Creating Effects As usual, a specific series of steps must be taken by the application in order to create a force feedback effect and prepare it for playback. Some of these steps may be optional depending on certain properties of the effect. In general, a force feedback effect is initialized and used by performing the following steps: • Create and acquire the DirectInput device • Query for force feedback support • Initialize a TDIEffect structure and the appropriate type-specific parameters structure • Create the effect object • Download the effect (sometimes optional) • Start the effect (sometimes optional) • Stop the effect (sometimes optional) #### Create and Acquire the DirectInput Device Force feedback is a subsystem of DirectInput. As such, an initialized IDirectInputDevice2 interface must be created before any force feedback functionality can be utilized. Please refer to Chapter 7, Input Techniques, for a detailed explanation of creating an IDirectInputDevice2 object. Specifically, we’ll be using the code from that chapter for communicating with the joystick. Other game controllers will function similarly. #### Query for Force Feedback Support While you could certainly require the user to have a force feedback joystick installed before using your application, it would be much wiser to allow input from any game controller attached to the system, and use force feedback only when it was available on the device. In order to determine if a device supports force feedback, we must call the GetCapabilities method of the IDirectInputDevice2 interface. This method is described in the Input Techniques chapter, but for the sake of completeness, its definition is reprinted here:
    function GetCapabilities(

    var lpDIDevCaps: TDIDevCaps                 // a TDIDevCaps structure

    ): HResult;                                 // returns a DirectX error code
The only parameter to this method is a pointer to a TDIDevCaps structure. Again, for the sake of completeness, it is defined as:
    TDIDevCaps = packed record

      dwSize: DWORD;                            // the size of the structure

      dwFlags: DWORD;                           // device flags

      dwDevType: DWORD;                         // device type identifier

      dwAxes: DWORD;                            // number of axes

      dwButtons: DWORD;                         // number of buttons

      dwPOVs: DWORD;                            // number of POVs

      dwFFSamplePeriod: DWORD;                  // force feedback sample period

      dwFFMinTimeResolution: DWORD;             // force feedback time resolution

      dwFirmwareRevision: DWORD;                // firmware version

      dwHardwareRevision: DWORD;                // hardware version

      dwFFDriverVersion: DWORD;                 // device driver version

    end;
The only member we’re concerned with at this point is the dwFlags member. If this member contains the flag DIDC_FORCEFEEDBACK, then we know that this device supports force feedback functionality. Incidentally, we can check for other DIDC_* flags to determine if the device supports such force feedback parameters as attack and fade (which refer to envelopes), deadband, negative coefficients and saturations, etc.
Previous | Table of Contents | Next

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 whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.