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
#### Initialize a TDIEffect Structure and the Type-Specific Parameters Structure Now that we have a device and we know it supports force feedback, it is time to define the type of effect we wish to create. This is accomplished by initializing a TDIEffect structure and a type-specific parameters structure appropriate for the desired effect. The first thing we should do is initialize the type-specific parameters structure. For example, if we were creating a periodic effect, we would need a TDIPeriodic structure, initialized in the following manner:
    PeriodicInfo.dwMagnitude := DI_FFNOMINALMAX;

    PeriodicInfo.lOffset := 0;

    PeriodicInfo.dwPhase := 0;

    PeriodicInfo.dwPeriod := DI_SECONDS div 20;
This indicates that we want a periodic effect that uses the maximum magnitude available on the device with no offset or phase shift and a relatively quick frequency. This will result in a vibrating effect, which we could potentially use to portray the feel of a powerful weapon such as a chainsaw or machine gun.
| Tip: Remember that the overall strength of any effect will be scaled by the gain set for the device.
Next, we need to define the axes on which this effect will be played. We’re using the joystick, so we’ll indicate that the effect should use both the x- and y-axis. We’ll use a small array of DWORDs, indicating the axes themselves using DIJOFS_* flags. We’ll also indicate the direction of the effect. In this case, we’ll be using the polar coordinate system, so we need a small array of longints (with as many elements as there are in the axis array). We simply need to indicate only the compass bearing of the desired direction in the first element, and set the last element to zero. This is accomplished like so:
    AxisArray[0] := DIJOFS_X;

    AxisArray[1] := DIJOFS_Y;

    DirArray[0] := 180*DI_DEGREES;

    DirArray[1] := 0;
With this completed, we need to initialize the TDIEffect structure. For example:
    EffectInfo.dwSize := SizeOf(TDIEffect);

    EffectInfo.dwFlags := DIEFF_OBJECTOFFSETS or DIEFF_POLAR;

    EffectInfo.dwDuration := INFINITE;

    EffectInfo.dwSamplePeriod := 0;

    EffectInfo.dwGain := DI_FFNOMINALMAX;

    EffectInfo.dwTriggerButton := DIJOFS_BUTTON0;

    EffectInfo.dwTriggerRepeatInterval := INFINITE;

    EffectInfo.cAxes := 2;

    EffectInfo.rgdwAxes := @AxisArray;

    EffectInfo.rglDirection := @DirArray;

    EffectInfo.lpEnvelope := nil;

    EffectInfo.cbTypeSpecificParams := SizeOf(TDIPeriodic);

    EffectInfo.lpvTypeSpecificParams := @PeriodicInfo;
Here, we’ve indicated that we have an effect of infinite duration, and that we’ll be using a polar coordinate system with device objects indicated by offsets. We’ve set the gain to maximum, so our effect will play with the strongest possible force available on the device (scaled by any gain set for the device itself). We’ve hooked the effect up to button 0 on the device, so it will automatically play when the user presses the button. A trigger repeat interval of infinite will really have no effect, as the effect will automatically continue to play until the button is released because of the infinite duration. We’ve also indicated the axes and direction, and we set up the cbTypeSpecificParams and lpvTypeSpecificParams members to indicate the size of and point to our type-specific parameters structure, respectively. #### Create the Effect Object Now that the effect is completely defined, it needs to be created. The CreateEffect method of the IDirectInputDevice2 interface is used to generate an initialized IDirectInputEffect object. The CreateEffect method is defined as:
    function CreateEffect(

    const rguid: TGUID;               // the effect type guid

    lpeff: PDIEffect;                 // pointer to a TDIEffect structure

    var ppdeff: IDirectInputEffect;   // returns an IDirectInputEffect object

    punkOuter: IUnknown               // COM aggregation

    ) : HResult;                      // returns a DirectX error code
The first parameter takes a GUID for the type of effect to be created. This can be either a predefined GUID for standard effects (listed below) or a GUID obtained from calling the EnumEffects method. The second parameter takes a pointer to the TDIEffect structure we initialized above. The third parameter takes a pointer to the IDirectInputEffect object, which will be instantiated when the method returns. The final parameter is used for COM aggregation and should be set to nil. Table 8-2: Predefined effect GUIDs GUID | Description
--- | ---
GUID_ConstantForce GUID_RampForce GUID_Square GUID_Sine GUID_Triangle GUID_SawtoothUp GUID_SawtoothDown GUID_Spring GUID_Damper GUID_Inertia GUID_Friction GUID_CustomForce | Constant forces Ramp forces Square wave periodic forces Sine wave periodic forces Triangle wave periodic forces Sawtooth up wave periodic forces Sawtooth down wave periodic forces Spring conditions Damper conditions Inertia conditions Friction conditions Custom forces
#### Download the Effect Once an effect is created, it must be downloaded into the device before it can be played. Downloading an effect is accomplished by calling the Download method of the IDirectInputEffect interface, which is defined as:
    function Download : HResult;                   // returns a DirectX error code
Now, it is not always necessary to download an effect. If the input device is in an acquired state when the effect is created, it is downloaded automatically. It is also downloaded automatically whenever the Start method is called (see below). For some effects, such as a triggered effect that was created before the device was acquired, the Download method must be used (as the Start method will not be called for triggered effects). Also, there is a little bit of a lag when an effect is initially downloaded, so explicitly downloading an effect before gameplay starts may reduce any detectable pause the first time an effect is to be played. As discussed earlier, a DIERR_DEVICEFULL error may be returned when using a force feedback effect. This indicates that the device has reached its maximum number of downloadable force feedback effects, and room must be created before a new effect can be used. An existing effect can be unloaded from a device by calling the Unload method of the IDirectInputEffect interface, which is defined as:
    function Unload : HResult;  // returns a DirectX error code
It is possible to use the DIPROP_FFLOAD flag with the GetProperty method of the IDirectInputDevice2 interface to retrieve the memory load for the device. You’ll need to use a TDIPropDWORD structure, and upon returning, the dwData member of this structure will contain a value in the range of 0 to 100, indicating the percentage of device memory in use. Checking this value before downloading a new effect may give you some indication as to whether or not the device will be able to hold the new effect without unloading an existing one.
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.