Microsoft DirectX 8.1 (C++)

Step 4: Creating an Effect

If the EffectFound value is no longer FALSE after effect enumeration, you can safely assume that Microsoft® DirectInput® has found support for at least one effect of the periodic type you requested by passing the DIEFT_PERIODIC flag. Knowing the effect GUID, you can now create the effect object.

Before calling the IDirectInputDevice8::CreateEffect method, you set up the following arrays and structures.

Arrays can be initialized when they, along with the structures, are declared.

DWORD      dwAxes[2] = {DIJOFS_X, DIJOFS_Y};
LONG       lDirection[2] = {0, 0};
 
DIPERIODIC diPeriodic;      // type-specific parameters
DIENVELOPE diEnvelope;      // envelope
DIEFFECT   diEffect;        // general parameters
 

Next, initialize the type-specific parameters. The values in this example create a full-force periodic effect with a period of one-twentieth of a second.

diPeriodic.dwMagnitude = DI_FFNOMINALMAX; 
diPeriodic.lOffset = 0; 
diPeriodic.dwPhase = 0; 
diPeriodic.dwPeriod = (DWORD)(0.05 * DI_SECONDS); 
 

To produce an effect of the chain-saw motor trying to start, briefly coughing into life, and then slowly dying, you set an envelope with an attack time of one-half second and a fade time of one second.

diEnvelope.dwSize = sizeof(DIENVELOPE);
diEnvelope.dwAttackLevel = 0; 
diEnvelope.dwAttackTime = (DWORD)(0.5 * DI_SECONDS); 
diEnvelope.dwFadeLevel = 0; 
diEnvelope.dwFadeTime = (DWORD)(1.0 * DI_SECONDS); 
 

Next, set up the basic effect parameters. These include flags to determine how the directions and device objects (buttons and axes) are identified, the sample period and gain for the effect, and pointers to the other data that you have just prepared. You also associate the effect with the joystick's fire button so that it is automatically played whenever that button is pressed.

diEffect.dwSize = sizeof(DIEFFECT); 
diEffect.dwFlags = DIEFF_POLAR | DIEFF_OBJECTOFFSETS; 
diEffect.dwDuration = (DWORD)(2 * DI_SECONDS);
 
diEffect.dwSamplePeriod = 0;               // = default 
diEffect.dwGain = DI_FFNOMINALMAX;         // no scaling
diEffect.dwTriggerButton = DIJOFS_BUTTON0;
diEffect.dwTriggerRepeatInterval = 0;      
diEffect.cAxes = 2; 
diEffect.rgdwAxes = dwAxes; 
diEffect.rglDirection = &lDirection[0]; 
diEffect.lpEnvelope = &diEnvelope; 
diEffect.cbTypeSpecificParams = sizeof(diPeriodic);
diEffect.lpvTypeSpecificParams = &diPeriodic;  
 

Finally, you can create the effect.

LPDIRECTINPUTEFFECT  g_lpdiEffect;  // global effect object
 
hr = g_lpDIDevice->CreateEffect(
                     guidEffect,     // GUID from enumeration
                     &diEffect,      // where the data is
                     &g_lpdiEffect,  // where to put interface pointer
                     NULL);          // no aggregation
if (FAILED(hr)) 
{
    return hr;
}
 

Note that, by default, the effect is downloaded to the device as soon as it has been created, provided that the device is in an acquired state at the exclusive cooperative level. You should now be able to compile, run, press the fire button, and feel the sputtering of a chain saw that's out of gas.

After creating an effect object, go to Step 5: Playing an Infinite Effect.