Master DirectX and DirectInput - force feedback game poles

zhaozj2021-02-08  215

Master DirectX and DirectInput - force feedback game poles

Jason Clark

Unconsciously, the games and multimedia programs under Windows have begun popular. Hardware is getting faster and faster, Windows has also become more flexible. Since Microsoft released DirectX, game developers have become more and more interested in other platforms. Many game developers have also fully transplanted their development efforts to Windows.

It is not easy to develop games for PC. From countless display cards and sound cards, developers have learned art in functionality and compatibility. They have to deal with page switching, segment memory structure, and bitter problems. And with the popularity of multiplayer games, developers must handle similar networks and communications. After DirectX is introduced, the game developers become relaxed. By providing the DirectX object provided for the developer, most of the annoying work has been simplified.

Is DirectX-based programs are ordinary Windows programs? Do you have to know COM? Is it worth using DirectX for a simple program? Do you have to use DirectX all components? This problem is definitely more.

This article will first introduce DirectX, then introduce one component DirectInput for DirectX. The demonstration describes the use of DirectInput, focusing on its powerful feedback.

DirectX revealed

DirectX is a set of components that provide Windows programs to system hardware more intimate control. (Table 1 lists the components and its roles of DirectX 5.0). So, what does intimate control mean?

Table 1: Components of DirectX 5.0

Component use DirectDraw high-speed 2D image DirectSound short response time sound output Direct3D high-speed 3D image DirectInput for game-oriented DirectSetup for game rods and other input devices, easy to install DirectX Component Directplay, communication and network support DirectShow video stream support DirectaniMation Animation record

The hardware control provided by DirectX is often described underlying control, which will make people loses the operation and other annoying things. In fact, the DirectX component contains many high-level APIs, making complicated work such as replication bitmaps and play sounds. Describe DirectX more accurately using "providing the program better than the past to the hardware". This is a significant feature in Windows, because in Windows, resources are shared and controlled by operating system.

The DirectX component complies with industrial standards called COM's binary objects.

Start DirectX

The following starts from DirectX installation. In most cases, a fun game will install DirectX for the system. To get the latest version, you should install DirectX to your system from the latest Microsoft Platform SDK. Platform SDK can be found in http://www.microsoft.com/msdn site or MSDN CD. By default, Microsoft Platform SDK is installed in the / mssdk directory under the root of the default drive. DirectX's header file is installed in the / mssdk / incline directory, the lib file is installed in the / mssdk / lib directory.

Platform SDK contains some very good DirectX examples and documents. Early released DirectX documents are very rough and some are wrong, and now the version has greatly corrected this issue. It is best to be familiar with these documents.

It has now been prepared for the installation of DirectX. Fortunately, it is not necessary to handle all the features of DirectX once. DirectX is a set of components that can be used separately. In fact, in the programming concept, different parts of DirectX have not contacted each other. They are merely have the same design style and objective: making Windows game programming easier. Is there any special place for programs using DirectX components? absolutely not. Programs using the DirectX component are WIN32-based programs that use ordinary WIN32 API sets and access all available operating system tools. In fact, DirectX can be used in the GUI program or in consistent procedures. You can use the Petzold-Style SDK programming development program or by basic class libraries such as MFC. In general, the only requirement is that most DirectX components need hwnd in the program, so at least there is a window.

Although the DirectX component is separated, the realization style and use of each component are the same. DirectInput is a very good starting point for learning DirectX because DirectInput is one of the easiest components.

Force

In the game, "force" is "force" in the game, which is the statement in the Movie "Star Wars", because DirectInput has joined the quite enhanced power feedback support. DirectX 5.0 Previously, DirectInput supported input from the mouse and keyboard, which is a useful but bored feature. DirectX 5.0, DirectInput is extended to support for the ability to propagate feedback to users in the form of physical strength.

If you cannot understand the above content immediately, use one game to explain it. Suppose you have just launched your favorite surreal 3D cross-country racing game, handshake feedback joystick. On the starting line, you can hear the empty voice of the racing engine, and you can feel the empty turn of the racing engine through the game pole! After the start of the game, you can feel the 嗡嗡 vibration of the engine high-speed rotation. When you travel to the rugged location, you will keep an electronic collision. The car hits it on the entire field, and your game pole will be the same. Racing wheel cards lead to the rut to leave the left, the game pole will also be pulled to the left! You can feel bumps, scratches, hit, and hit each time.

Now, a unique force feedback device with a Windows driver that supports DirectInput is Microsoft's Sidewinder Force Feedback Pro. This status quo will not continue too long, new devices and new drivers for existing equipment will soon enter the market.

Analysis DirectInput

DirectInput consists of three objects: DirectInput, DirectInputDevice, and DirectInputEffect (see Table 2). DirectInput is a high-level object that allows for basic initialization and lookups of related input devices via DirectInput objects. DirectInput objects ultimately used to create a low-level DirectInputDevice object. Each of DirectX uses the same method, first create a high-level object, such as DirectInput or DirectSound object, and then create a low-level object with hardware to actually communicate.

Table 2: DirectInput object

Object Description DirectInput encapsulates the high-level DirectInput function, enumerate equipment and to create DirectInputDevice objects. DirectInputDevice interfaces with physical input devices, such as game rods, including interfaces that collect and set device status information, and to create DirectInputEffect objects (for force feedback devices). DirectInputEffect encapsulation can provide a simple effect on "play" on the device, provide functions such as start, stop, and set strength feedback effects. DirectInput objects are the most easily understood in three objects. In fact, it only provides five functions in an interface form iDirectInput (see Table 3). This is a very important part of DirectInput because it is the starting point.

Table 3: IDirectInput interface

Member Function Description CreateDevice Creates a DirectInputDevice object and returns a pointer to its IDirectInputDevice interface. Enumdevices Call a callback function for each device that matches a given standard, each callback function provides a GUID, which can be used to create a DirectInputDevice object in CREATEDEVICE. GetDeviceStatus tests whether the physical device is connected to the system. Initialize If the DirectInput object is created using CocreateInstance, you must call the Initialize member before use. If the DirectInput object is created using DirectInputCreate, then it has been initialized. RunControlPanel runs the Windows Control Panel for your device to allow users to install new devices or change the configuration of existing devices. Game pole calibration can be done here.

Create a DirectInput object

In order to create a DirectInput object and get its IDirectInput interface pointer, you should use one of two methods in the program initialization phase.

The first method is quite simple. DirectX provides an assistant function DirectInputCreate to create and initialize the DirectInput object. It is declared in the header file DINPUT.H with all DirectInput's functions, interfaces, and macro definitions. The actual function body is in the DINPUT.LIB file.

DirectInputCreate is defined below:

HRESULT WINAPI DirectInputCreate

Hinstance hinst,

DWORD DWVERSION,

LPDIRECTINPUT * LPLPDIRECTINPUT,

LPunknown Punkouter

);

The first parameter is an instance of the application. The second parameter is the DirectInput version required by the program, which is usually used to define as the current version using the DirectInput_Version macro. The third parameter is most important. It is difficult to understand if it is very strange to COM. It is the address of the pointer to the iDirectInput interface. A variable that should be defined in the program (which can be globally) and the address is passed to DirectInputCreate as the third parameter.

The last parameter is called PUNKOUTER, which is related to aggregation in COM technology, and can be ignored by NULL security. The return value is a HRESULT. It is the standard return type of COM. You can check the return value with the possible return value, or you can use the COM macro definition SUCCESS or FAILED to check.

Using DirectInputCreate can easily create high-level objects and get its primary interface pointer. This is another design method of DirectX, each DirectX component provides assistant functions to create high-level objects such as DirectInputCreate or DirectDrawCreate. You can create a DirectX object in a program, however, these functions actually create a COM object. This work can also be done with standard Win32 API functions called CocreateInstance. This will lead to the second middle method of creating a DirectInput object. Creating a COM object with CocreateInstance in Win32 is very common. If you have created other COM objects in the program, developers may want to use it to create a DirectX object. Because the COM object is registered in the system during installation, the only thing you need to know is the GUID of the object, use it to create an instance. All GUIDs that create DirectX objects are declared in the header file and define in library DXGUID.LIB. You can pass a predefined GUID to CocreateInstance, let Windows create objects for you.

CocreateInstance is defined as follows:

Stdapi CocreateInstance (

Refclsid rclsid,

LPunknown Punkouter,

DWORD DWCLSCONTEXT,

Refiid RIID,

LPVOID * PPV

);

The first parameter is to create the GUID of the object, the directx defined GUID is a GUID structural variable called CLSID_DirectInput. The second parameter is a familiar PUNKOUTER, and it can also be ignored with NULL. The third parameter dwclsContext Defines where the COM object is created, and DirectX only supports the internal server, so you must use CLSCTX_INPROC_SERVER.

The fourth parameter is the truly different ways. Remember that the COM object provides an interface, like the object itself, the interface is also identified with GUID. Using the first method, you cannot choose the resulting interface, always get idirectInput. Using CoCreateInstance can request any interface supported by the object, the method is to predefined GUIDs for the interface. But in DirectInput is meaningless, because the only useful interface of the DirectInput object is iDirectInput. Other DirectX components support multiple useful interfaces. (For example, the DirectDRAW object can be operated with the IDirectDraw or iDirectDraw2 interface.)

The last parameter is the actual address of the interface pointer variable in the program.

Now you have an interface of an object and an object. The CoCreateInstance method also needs another step: you must first call an interface function to initialize the object. DirectInputCreate provides an initialized DirectInput object, but CoCreateInstance does not have DirectInput awareness, so the initialization member function of the iDirectInput interface must be called. Assume that the IDirectInput interface pointer variable is defined as follows:

LPDIRECTINPUT G_LPDI

You can call the initialization function as follows:

g_lpdi-> initialize (Hinstance, DirectInput_Version);

Since choosing this standard method to create an object, you have to pay attention to other criteria for COM, such as need to call Coinitialize and Couninitialize.

Use the DirectInput object

Once you have a DirectInput object, you can use it to create a DirectInputDevice object to manage specific devices in your system. Creating a DirectInputDevice object To use the CreateDevice function, it is one of five functions as part of the IDirectInput interface. CreateDevice requires the GUID of the requesting device, returns the iDirectInputDevice interface pointer for the new DirectInputDevice object. HRESULT CREATEVICE

REFGUID RGUID,

LPDirectInputDevice * LPLPDIRECTINPUTDEVICE,

LPunknown Punkouter

);

These content look familiar because it is similar to CoCreateInstance and DirectInputCreate. However, it is not fully prepared to start the DirectInputDevice object, because the GUID of the device is required before creating the DirectInputDevice object.

The DirectInput library predefines two guid_syskeyboard and guid_sysmouse to create a DirectInputDevice object. The DirectInputDevice object of the corresponding device will be delivered directly to the CreateDevice function.

Note that it is strange to lack a predefined GUID for the joystick. In Windows, there is usually a system keyboard and a system mouse. On the other hand, the system itself does not use the joystick. You can install one or more game rods, but the scope of system management is limited to driver levels. The system specifies a special system state for these devices, nor does it use these devices in a daily transaction. Therefore, it is unreasonable to define the GUID for the joystream.

So how can I find the GUID of the game pole connected to the system? To get them, you must enumerate the equipment. The system equipment and performance are quite common in DirectX. To list the input devices in your system, you need to use the EnumDevices function. Enumdevices is part of the iDirectInput interface, as follows:

HRESULT ENUMDEVICES

DWORD DWDEVTYPE,

LPDIENUMCALLBACK LPCALLBACK,

LPVOID PVREF,

DWORD DWFLAGS

);

Note This function is the same as other enumerated APIs in Windows, such as EnumWindows. The second parameter is a callback function. The third parameter is the 32-bit value defined in the program. The first parameter is the type of device that wants to be listed. For the game rod, it is DidevTyPE_JOYSTICK (all device type columns in Table 4). The last parameter is the sign of the device you want to listed in detail. The flag now support is Diedfl_attachedonly and Diedfl_AllDevices (both flags are mutually exclusive), and DiedFL_ForceFeedback, which represents the force feedback device, can be able to or other two flags or operations.

Figure 4: Definition listing device

The following defined values ​​can be passed to Enumdevices to select which type of input device. In addition, subtypes are also supported, see the documentation of the DIDEVICEINSTANCE structure in the SDK.

Value Description DidevType_mouse lists the mouse device (standard, trackball, etc.) DIDEVTYPE_KEYBOARD to list keyboard devices (standard, keypads, etc.) DIDEVTYPE_JOYSTICK to enumerate the game rod equipment (joystick, stepwheel, direction rudder, etc.) DIDEVTYPE_DEVICE lists other devices

When Enumdevices enumerates the input device in the system, repeatedly calls the callback function. The callback function is defined as follows:

Bool Callback EnumProc (LPCDIDEVICEINSTANCE LPDDI, LPVOID PVREF); because the callback function is defined by the user program and passes it to Enumdevices, it is the most suitable place to call CreateDevice until the sufficient DirectInputDevice object that satisfies the need is created. However, the callback function is not necessarily to be so real, so you can simply save all the GUID of the device in a table, in the later code.

The callback function accepts two parameters. The second parameter is the 32-bit value that the program definition is passed to Enumdevices. More importantly, the first parameter passes a pointer to a structure that includes many information about a single device that matches the list. This is a DIDEVICEINSTANCE structure. The most important information in this structure is the GUID of the device, saved in the GUIDINSTANCE member of the structure.

When DirectInput is completely completed in the program, the Release member of the IDirectInput interface should be called. This tells the DirectInput object to release yourself. In DirectX, it is best to develop habits of the object, starting from a low-level object, and ending to a high-level object. Under normal circumstances, the program will call a part of the routine-routine-routine party. This is the necessary steps using each DirectX component, but also the necessary steps using each COM component.

Now I have used the CreateDevice member function to get an interface of the DirectInputDevice object, and prepare for the actual physical device that starts processing with the system connection.

Use the DirectInputDevice object

Each instance of the DirectInputDevice object is related to specific devices in the system. This object provides more control and capabilities for system hardware, thereby achieving the memory of DirectX. The following discusses what you have next steps after the DirectInputDevice object.

I have an interface pointer for the IDirectInputDevice interface, what is now? First, set the data format of the device. This function is an interface member function by calling SetDataFormat. Setting data formats include countless possible decisions, including axis information, opposite or absolute coordinate information, and the like. All of these details are passed to this function via a structure called DIDataFormat. In fact, SetDataFormat unique parameters are pointers to this structure.

Details of this structure will make people. Thanks, this work is not necessary, because DirectInput has defined several DidataFormat structural variables that can be used to compare common input devices: c_dfdikeyboard, c_dfdimouse, c_dfdijoystick, and c_dfdijoystick2. To set the data format for the ordinary feedback joystick, you can use the following call form:

LPDID-> setDataFormat; & c_dfdijoystick;

In this example, LPDID is a pointer to the IDirectInputDevice interface.

After setting the data format of the device object, you need to set the collaboration level of the device. Because the collaboration level is very common in the entire DirectX, so you have to do this. Most direct processing system hardware DirectX objects have a member of the interface called SetCoopeRATIVELEVEL function. This function is important because it defines the control level of the program manipulation and the hardware related to other processes in the system. Like other DirectX objects, only the collaborative level can make the DirectInputDevice object. To understand the level of collaboration, you need to be familiar with the acquire function. Calling this function is to obtain actual access to the physical device (do not mix the logically DirectInputDevice object). Conversely, UNACQUIRE functions release access to physical devices. Below is the definition of the function setCoopeRATIVELEVEL:

HRESULT SETCOOPERATIVELEVELevel

HWND HWND,

DWORD DWFLAGS

);

HWnd is the main window of the program. The flag is the combination of some of the following values ​​or operations: DISCL_BACKGROUND, DISCL_FOREGROUND, DISCL_EXCLUSIVE, DISCL_ NONEXCLUSIVE.

If the logo parameter is in DISCL_EXCLUSIVE, the program is unique to access the physical device after obtaining the device. On the other hand, if DISCL_NONEXCLUSIVE is selected, there can be multiple processes in the system simultaneously obtain and use the device. If you have DISCL_BACKGROUND, the program will not lose physical devices. However, like the Ctrl Alt Del combination key is pressed such a system event to remain implied in the "UNACQUIRE" program. If DISCL_ FOREGROUND is used, the program will automatically release the physical device when not an active window. This is the meaning of passing the program main window handle to SetCoopeRATIVEVELEvel. DirectX automatically adjusts the device sharing according to whether the window is the current active window of the system.

So what is the meaning of all these values? The following example will be given. If the collaboration mode of the force feedback rod is DISCL_FOREGROUND | DISCL_EXCLUSIVE, then as long as the program is active, it is possible to read data from the joystick and play the feedback effect (force feedback requires Exclusive-Level collaboration). As long as the user chooses other programs, the program will lose the device to access the physical device, and the newly activated program can access the device. This means that when you switch to the debugger window, the program will lose the control of the game rod because the window is not active.

What is the situation in which the collaboration level of the same jam rod is set to DISCL_BACKGROUND | What is the situation? The program will access the joystick, regardless of the state of the window. But now other processes in the system cannot get the joystick, unless the program releases the game pole, no matter what the user is doing!

Very obvious, DISCL_FOREGROUND | DISCL_EXCL_BACKGROUND | DISCL_EXCLUSIVE should be used in the debug version in the formally released product. But not always choice. For example, if the device is a system keyboard, DirectInputDevice wants to use exclusive use and call SetCoopeRATIVELEVEL will fail. This is because the operating system wants to allow users to freely switch from one program to another. Similarly, DirectInputDevice does not allow the system mouse to be requested by collaborative level DISCL_BACKGROUND | DISCL_EXCLUSIVE requests system mouse. Windows does not want a program to completely contact the user with the operating system.

Before you can read information from the physical device or send information to the physical device, you must use Acquire to obtain the device. The UNACQUIRE function release device is explicitly used when using the temporary or permanent end device. However, UNACQUIRE is not the only way to lose device control. If you use the DISCL_FOREGROUND flag when the collaboration level is set, the main window of the program is no longer the device to be explicitly released when the active window in the system. That is to say, between program call acquire and actually attempt to read information from the device, it is possible to lose the occupation of the device. So you need to check the return value to capture such errors and ready to reagent at any time.

Differential points about Acquire and UNACquire: DirectX owns the device when the program gains a single-level device. For example, if the mouse is obtained by DirectX, the button in the program window will not respond to the mouse. That is to say, if you want Windows to respond to the device, you should release the device. In other words, if you do not want DirectInput to read data from the device, call UNACQUIRE.

After setting the collaboration level of the device, you should then configure other settings for the device. After obtaining the equipment, then you should start using the getDeviceState function to detect the input data. When completing the operation with the device object, call UNACQUIRE Release the DirectInputDevice object. There is a difference in detail between the equipment and the device; how to explain the joystick and keyboard, it should be able to provide sufficient basic knowledge for reading input from other devices.

keyboard

The keyboard is the device that is easier to read so far. In fact, you can read the keyboard status after setting the data format, collaboration level, after obtaining your device. Read the keyboard status to use the getDeviceState member of the iDirectInputDevice interface. GetDeviceState is assembled with the status information about the physical device, and the type of structure is determined by the call to setDataFormat in front. For keyboards, this data structure is an array of simple 256 bytes. Each byte corresponds to a key on the keyboard. If a key is pressed, the corresponding byte is set.

DirectInput defines a constant that is prefixed with Dik_xxx, which can be used to index the byte array to find data about the specific key. For example, if you want to check if the right shif button is currently pressed, you can use Dik_RSHIFT definitions:

GetDeviceState (256, (lpvoid) ckeyboarddata);

IF (CKEYBOARDDATA [DIK_ RSHIFT] & 0x80)

Dowhatever ();

CKeyboardData is a 256-byte buffer. It is almost as simple, but I have to remember, regardless of when getDeviceState returns Dierr_Inputlost, you must use Acquire to get the device. This situation occurs when the user switches from the program from the program.

It is important to request DirectInput buffer keyboard information. This requires a buffer and uses setProperty to set buffer sizes for the device. There is no discussion in this article, but this technology is very useful when the program cannot be quite frequently checked. The user may pick up a key between the two getDeviceState calls in the program, if DirectInput does not bury the keyboard data, this hit button is lost.

Jam

The game pole is very fun. With its nice name (Joystick - originated for happy rod), this device adds a lot of fun to the game experience, and also adds something to the programmer's experience. Normally, by calling the CREATEVICE member of the IDirectInput interface (and object), this is also applicable to the game pole. However, developers want to immediately upgrade the interface to iDirectInputDevice2, then you can use the QueryinterFace call request CreateDevice to return to a new interface using the queryinterface call:

HR = lpdideviceJoyStickTemp-> queryinterface (IID_IDirectInputDevice2,

(void **) & g_lpdidevicejoystick;

If successful, you can release the original interface and start using a beautiful new iDirectInputDevice2 interface. But why do you want to do this? The IDirectInputDevice2 interface provides all the features of iDirectInputDevice, and there are two other important features: support query devices and support feedback devices.

Second, some considerations are required. I still remember that setDataFormat defines the type of data returned by getDeviceState. For the joystick device, one of the two predefined variables of c_dfdijoystick or c_dfdijoystick2 will be set to DiJoyState or DiJoyState2 structure. Which of the main depends on which type of game is to use. Browse members of these structures should be helpful to find out this problem.

Like all input devices, set data formats and collaborative levels for the joystick. The game pole often needs more attention than the keyboard. This is because now there is almost no perfect game rod, so the program should check to ensure that the controlled equipment can meet the requirements. If you can't, adjust the requirements or remind the user that the game pole is too backward! The ability of the device can be called and the iDirectInputDevice interface should call the member function getCapabilities probe.

This will lead to another discussion point for all DirectX components. DirectX provides a wide range of support for a variety of devices. Software development environment and use environments may have a big difference, different computers support different levels of DirectX feature. Writing software using DirectX, you need to check your hardware. In the worst case, if a feature is not supported, you can exit the program. The best situation is of course the need to intelligently adjust itself according to the lack of characteristics.

You need to set the characteristics of the device before starting the input from the device. These features include such detalations such as the range of return values, the central point of the game rod. This work is complete by the function setProperty, quite complex.

SetProperty Sets the feature of the device. First, you must use some information about the settings to be changed to fill in a data structure. Please refer to the document in the Platform SDK to get all data structures. Each structure begins with a DiPropheader structure, and this structure fills in the information describing the settings to be changed. Then, the portion remaining in the structure is fill in the structure of the data specific to the changed setting. Finally, call setProperty, parameter is the pointer to the Dipheader section of the Dipropheader section in the structure. The following code snippet sets the vertical range of the joystick to -100 to 100:

DiproPRANGE DIPRANGE;

DipRange.diph.dwsize = sizeof (DIPRANG);

DipRange.diph.dwheadersize = sizeof (Diprange.DIPH);

DIPRANGE.DIPH.DWOBJ = DiJOFS_Y;

DipRange.diph.dwhow = DIPH_BYOFFSET; DIPRANGE.LMIN = -100;

DIPRANGE.LMAX = 100;

g_lpdidevicejoystick-> setproperty (diproP_range, & diprange.diph);

The most difficult part in this structure is Diph.dwobj and Diph.dWhow. Diph.dwhow describes what information in Diph.dwobj. Diph.dwobj describes which property is set. In most cases, the value of Diph.dwhow is DIPH_BYOFFSET, and the value of Diph.dwobj is a predefined offset passing to the structure of SetDataFormat.

It should be noted that objects that include the device, including buttons and other features. This work is complete by the EnumObjects function. When doing this, an object marker should be provided. Pass this flag to Diph.dwobj, fill in Diph.dWhow members as DIPH_BYID.

Before reading data from the device, set the minimum and maximum values ​​for the X and Y axes of the device. Once the device properties are set, you can get the device and start obtaining data from the device. Getting data from the joystick is different from the keyboard or mouse acquisition data because the joystick is the query device.

The keyboard and the mouse will cause the hardware interrupt, process the driver in the system, and to update the data returned by calling getDeviceState by DirectInput. Query devices (such as most game rods) do not generate hardware interrupts, but DirectInput must be informed from the device to obtain status information. This work is done by calling the Poll member function of the IDirectInputDevice2 interface. At this point, check if the device needs to be re-obtained. After the device is successfully queried, you can call getDeviceState to get status information.

If you use a C_DFDIJOYSTICK variable when calling setDataFormat, GetDeviceState will populate a DiJoyState structure with the current status information of the game rod. The content of this structure depends primarily on the characteristics of the physical device and settings for SetProperty. For example, if the LY member in the structure is equal to -50, and the range of the Y-axis is set to -100 to 100, then the joystick is in the center and the top end in the vertical direction. The program should be ensured that the range of the device is set to suit the value of the demand. In order to obtain data from the joystick device, the program should query the device.

Use DirectInputEffect

First, some power feedback techniques should be explained. The force feedback device is an apparatus capable of generating a force that the user can feel, these force is called an effect, such as a bump effect or a force that continues to push the joystick to the upper right. These effects are "play", the effect is played by the program, or the function calls responds, or automatically reacts the user button.

DirectInput currently supports approximately one different effect type (see Table 5). These effects range from the low-level continuous effect controlled by the program, to the advanced tilt or fluctuation effect controlled by DirectInput or the device. There are four basic types of basic types: sustainability, tilt effect, cycle effects and conditions. The continuation is the force that does not change the strength in a single direction. The tilt effect is the continuous force of the intensity linearly changed. The cycle effect is a change in a given axis, and its magnitude or strength is defined by the cycle effect. The condition is the effect of responding to the interaction of the user and the joystick. This effect may be like a spring, the higher the joystick, and the stronger rebound is stronger.

Table 5: Type of DirectInput

GUID Description Using the method to decline the GUID_ConstantForce fixed strength, the continuous tension of the specific direction. Use the Diconstant force structure as part of the DIEFFECT structure to achieve continuous. GUID_CUSTOMFORCE sequence continuous is transferred to the device, playing in order. The DICUSTOMFORCE structure is used to define power. Guid_Damper increases the conditional effect along the movement along the coordinate axis. A specific type of structure that achieves this effect is a Dicondition structure. Conditional effects are usually not supported. GUID_FRICTION hinders the conditional effect along the coordinate axis. A specific type of structure that achieves this effect is a Dicondition structure. Conditional effects are usually not supported. Guid_inertia increases the conditional effect of acceleration movement along the axis. A specific type of structure that achieves this effect is a Dicondition structure. Conditional effects are usually not supported. The magnitude of the GUID_RAMPFORCE in a specific direction increases or decreases. The DirampForce structure is used as the type of related part of the DIEFFECT structure. GUID_SAWTOOTHDOWN force instantly reaches the maximum and linearly reduces the minimum cycle effect. The specific type of structure required is a Diperiodic structure. The specific type of structure required for the GUID_SAWTOOTHUP force from the minimum linearity and then instantly dropped to the minimum cycle effect, is a Diperiodic structure. GUID_SINE Strove Changes Periodic Effect. The specific type of structure required is a Diperiodic structure. GUID_Spring increases the conditional effect of increasing the relative distance of a mid point. A specific type of structure that achieves this effect is a Dicondition structure. Conditional effects are usually not supported. GUID_SQUARE transients transition cycle effects between maximum and minimum. The specific type of structure required is a Diperiodic structure. GUID_TRIANGLE force is in the largest cycle effect of linear changes between maximum and minimal. The specific type of structure required is a Diperiodic structure. All of the following works related to the powerback gaming rods are for Microsoft Sidewinger Force Feedback Pro, this is to say that some details in this article may have some problems.

Before you create a feedback effect, you can get a good idea before you get a good idea. Although this is not necessary, the device must be obtained before the effect can be subjected to the device. This is especially important for playing the force effect of playing the user's pressing button.

To create an effect, first create an instance of the DirectInputEffect object for each of the effects used. This work is done by calling the CreateEffect member function of the IDirectInputDevice2 interface. This function requires the effect of GUID, and pointers pointing to the DIEFFECT structure, which is filled in the details of the effect. Finally, Createeffect returns a pointer to the iDirectInputeffect interface, which is a parameter of Createeffect. The core part of this call is concentrated in the DIEFFECT structure.

The DIEFFECT structure is defined as follows:

Typedef struct {

DWORD DWSIZE;

DWORD DWFLAGS;

DWORD DWDURATION;

DWORD DWSAMPLEPERID;

DWORD DWGAIN;

DWORD dwtriggerbutton;

DWORD DWTRIGGERREPEATINTERVAL;

DWORD CAXES;

LPDWORD RGDWAXES;

LPLONG RGLDIRECTION;

LPDIENVELOPE LPENVELOPE;

DWORD CBTYPESPECIFICPARAMS;

LPVOID LPVTYPESPECICIFICPARAMS;

} DIEFFECT, * LPDIEFFECT;

DWSIZE members are the number of bytes of this structure. DWFLAGS indicates the coordinate type used by the effect, and is the use of an offset method or an ID method description button (set forward to the setProperty described above). Typically, it can be set to DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS, ie the button uses an offset description, the coordinates use the XYZ coordinate form. DWDURATION indicates how much milliseconds play. Note that dwduration can be set to Infinite. DWSAMPLEPERIOD Description Effect How much milliseconds for playing a cycle. Different devices support different cycles. In practice, the Sidewinder game rod supports the cycle of no more than 1 second, not less than 1/80 seconds. DwGain can view the main amount of the effect because it indicates how powerful. This value ranges from 0 to 10,000.

DWTRIGGERBUTTON and DWTRIGGERREPETINTERVAL are used to set the buttons that trigger results playback, and repetition frequencies. Of course, you can set the effect to the button with the button by setting the value of dwtriggerbutton value to Dieb_Notrigger. Otherwise, DWFLAGS defines the description button through the ID or offset mode. Because the offset method does not need to call Enumjects, the value can be specified as DiJOFS_ Button0 and DiJofs_Button1.

CAXES member description effect will affect several axes. RGDWaxes point to a DWORD array of shafts that describe the shaft included, each shaft in an array is a member. Like the button, the shaft is also specified with an offset or ID. The general offset values ​​include DiJOFS_X and DiJOFS_Y.

Similarly, the RGLDirection member points to a long-type array, each shaft is a member. In the Cartesian coordinates, (y = -1, x = 1) is the same direction in the same direction (Y = -10, x = 10). That is to say, if you want to get the oblique force in the direction of 45 degrees, you should adjust the relative size of the two values. For example, (y = -10, x = 1) describes the direction of the same quadrant with the above example, but it is obviously close to the Y-axis.

Effects can also have a package that describes them. Fill a DIENVELOPE structure and fill in the address of the LPENVELOPE. The package can affect the number or strength of the effect within a period of time. Among them, the start level is the beginning of the effect, and the startup time indicates how much milliseconds cost the force maintenance stage. Attenuation levels are the effects of the final achievement in the package, and the attenuation time is decaying how much fond. The package can be used to make the force effect of the initial state, then slowly attenuate. How to change the effect in Figure 1.

Figure 1: Packing effect

The last two members of the DIEFFECT structure are CBTYPESPECIFICPARAMS and LPVTYPESPECIFICPARAMS. They store the number and address of the structure specific to the created effect type. Information about what structure of a particular type of effect is shown in Table 5.

After filling out this structure and calls Createeffect, you will get a pointer to the iDirectinputeffect interface, and now you can use this interface to play effect, change the effect, and so on. If you do not contact your button, you must play and stop using the Start and STOP members of the IDirectInputEffect interface. If the effect is associated with the button, then it is passed to the device when creating; otherwise, the effect is automatically subjected to the device when playback. If the program must re-get the device, all the effects associated with the button must be downloaded to the device by clear calling Download members.

The effect can be uninstalled with unload members, and can be reset by resetting the new DIEFFECT structure by passing the SETPARETERS member function. When the program uses the effect, you must call the Release member of the interface. Presentation example

Figure 2: Demo program

First, you should establish a demo code and run, you should see a game rod configuration window (see Figure 2). Using the game rod can move the middle, the upper left corner of the window is the coordinates and input status information. If you have a powerful feedback rod, you should feel a pair of different power by pressing the buttons 1 and 2. If you hit the villain to the edge of the window, you should feel the collision effect.

This example illustrates the use of DirectInput. There is still a considerable number of code here, there is no direct relationship with DirectInput. These codes are divided into modules according to the function score. Main.cpp is the basic WinMain model file and window creation code. In addition to calling the initialization function, this part of the code is basically not related to the other parts of this article. It creates a window to enter the message loop. WndProc.cpp contains the window process of the program window.

Demo.cpp starts meaningful code. Whenever "Demo" is mentioned, it is a program game. For example, the initdemo function sets status data for graphics and creates some time and threads required. In addition to initialization, this demo runs in the second thread. This thread attempts to read the input and refreshed status data, 32 times per second. Then make the window to allow the main thread to reselect the window. That is, a repetition of the input and state changes, or a demo cycle, about 1/32 seconds. Therefore, regardless of how much frequent refresh is displayed, the input response speed will remain consistent.

Dx.cpp contains very small initialization and end processing required by DirectX, and then calls functions that complete special DirectInput work. In addition to Coinitialize and CounInitialize, the DXInput module contains all the content mentioned herein. The function is listed in the order used in the demo program, each only lists once. Note that most of DirectInput is completed in initialization. The lengthy task is divided into several functions columns in Table 6.

Table 6: Function of DXInput.cpp

Member Function Description INITDIRECTINPUT initializes the DirectInput object and the DirectInputDevice object for the system keyboard. Enumjoy enters the device's callback function. This function creates DirectInputDevice for the first game rod installed in the system. InitforceFeedback If the game rod is found to be fettered, this function is set for power feedback effects. INITRAMPEFFECT, INITBUMPEFFECTS, INITWAVYEFFECT These functions each set an effect. These effects demonstrate several different effects in DirectInput and should be useful for creating new effects.

Another point in this module is a function that demo repeat call. Forceeffect Play an existing effect, getKeyboardInput gets the keyboard input, getJoyStickInput gets the game rod input. Finally UninitDirectInput ends all everything.

To get a complete source code, visit the MSJ's Web site http://www.microsoft.com/msj.

转载请注明原文地址:https://www.9cbs.com/read-3224.html

New Post(0)