Delphi Graphics and Game Programming Exposed! with DirectX For versions 5.0-7.0:Input Techniques
Search Tips
Advanced Search
Title
Author
Publisher
ISBN
Please Select
-----------
Artificial Intel
Business & Mgmt
Components
Content Mgmt
Certification
Databases
Enterprise Mgmt
Fun/Games
Groupware
Hardware
IBM Redbooks
Intranet Dev
Middleware
Multimedia
Networks
OS
Productivity Apps
Programming Langs
Security
Soft Engineering
UI
Web Services
Webmaster
Y2K
-----------
New Arrivals
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
Reading Input Data
As we previously mentioned, our secondary thread will handle the task of retrieving the input data from the buffer. Thus, all of the code we are about to review is located in the Execute method of our secondary TThread object.
The first item of note in the Execute method concerns the notification events we created. After checking for termination, the very first task we perform in the thread is to call the WaitForMultipleObjects Win32 API function. This function halts execution of the thread until one or more event objects become signaled (known as blocking the thread). The WaitForMultipleObjects function is defined as:
function WaitForMultipleObjects(
nCount: DWORD; // the number of objects in the array
lpHandles: PWOHandleArray; // a pointer to an array of object handles
bWaitAll: BOOL; // wait flag
dwMilliseconds: DWORD // timeout interval
): DWORD; // returns an array index
We pass in our array of object handles and the number of objects in the array in the first two parameters. We only want the thread to be blocked until either of the events becomes signaled, so we set the third parameter to FALSE. We want the thread to wait indefinitely until one of the events is signaled, so we set the final parameter to INFINITE. This function call will not return until either of the events becomes signaled.
When the function does return, we need to check its return value. We subtract the constant WAIT_OBJECT_0 from this return value to get the index in the array of the object that became signaled. If the Quit event was signaled (indicating we are terminating the application), we should immediately terminate the thread and exit the Execute method. Otherwise, we know it was the mouse event that became signaled, and we are ready to start retrieving mouse input data.
Note: We set the Quit event to signaled using the SetEvent Win32 API function in the main forms OnDestroy event. We must also use the CloseHandle Win32 API function to dispose of the event handles we created. See the full example on the CD for details.
Once past this, we make use of our critical section object. A critical section is a device that is used to synchronize access to variables and objects from multiple threads. This is accomplished by calling the TCriticalSections Enter method. If one thread calls the Enter method of a critical section after another thread has already called it, this second thread is blocked until the first thread calls the TCriticalSections Leave method. At this point, the other thread becomes unblocked, and any other thread will be blocked in a similar fashion until the current thread calls the Leave method. By using critical sections, we can allow only one thread at a time access to specific variables and objects. This is important, as this secondary input thread will be drawing to the primary DirectDraw surface, and surfaces can only be accessed by one thread at a time. It will also be updating global variables that track the mouse cursor, as well as a list of mouse click events that are used by the primary thread to determine if the user clicked on something interactive.
Now we are ready to being retrieving input data from our buffer. This is accomplished by calling the IDirectInputDevices GetDeviceData method. The GetDeviceData method is defined as:
function GetDeviceData(
cbObjectData: DWORD; // the size of the device data structure
rgdod: PDIDeviceObjectData; // a pointer to the device data structure
var pdwInOut: DWORD; // a variable indicating the number of elements
dwFlags: DWORD // data removal flags
): HResult; // returns a DirectX error code
The first parameter is set to the size of a TDIDeviceObjectData structure. The second parameter is a pointer to an array of TDIDeviceObjectData structures which, upon return, will contain the buffered device data. The third parameter indicates how many elements to retrieve, and should be equal to or less than the number of elements in the array. When this method returns, it will contain the actual number of elements retrieved. The last parameter indicates if the data should be removed from the buffer. Setting this to zero removes the data from the buffer; a value of DIGDD_PEEK leaves the buffer intact.
Note: You do not have to remove the entire contents of the buffer at once. You may remove them one at a time or in similar small increments, if desired.
This method will return one TDIDeviceObjectData structure for each individual input event that has occurred on the device since the last time data was retrieved. This means there is one event for a button press, one for a button release (even if it was the same button), one for every individual movement along each axis, etc. This is why it is important to set the buffer size to an appropriate number, as it is easy to overflow the buffer if a lot of activity is occurring.
The TDIDeviceObjectData structure contains all the information necessary to report any input event on the specific device. The TDIDeviceObjectData structure is defined as:
TDIDeviceObjectData = packed record
dwOfs: DWORD; // the device object identifier
dwData: DWORD; // the data
dwTimeStamp: DWORD; // when the event occurred
dwSequence: DWORD; // the event sequence number
end;
The first member, dwOfs, indicates what actually caused the input. This value is very specific to the type of device being used. In the case of buffered keyboard data, this value will be one of the DIK_* key values. For mice, this could be DIMOFS_X, DIMOFS_Y, or DIMOFS_Z to indicate movement along one of the axes, or DIMOFS_BUTTON0, DIMOFS_BUTTON1, or DIMOFS_BUTTON0 to indicate a change of state in one of the mouse buttons. There are similar DIJOFS_* values defined for various buttons and axes on joysticks. The dwData member contains the data for the input event, and again is very specific to both the device and the object on that device that signaled the input event. In the case of one of the axes, dwData will contain either relative or absolute axis movement, in arbitrary units. In the case of buttons, if the high bit is set, the button was pressed; if it is clear, the button was released.
If we enter a loop to retrieve one input event at a time, we can examine all of these members and update various global variables accordingly. In our example on the CD, we add any axis movement to global mouse cursor variables, and then ultimately clip them to the boundaries of our DirectDraw screen resolution. While our example is concerned only with button presses, we do store each mouse button press in a list of button press objects, storing the location of the press and the button that was pressed. We can use this later in our application logic to determine if the user clicked on an interactive game element.
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.
Wyszukiwarka
Podobne podstrony:
143 07 (10)MIKROBIOLOGIAwyk 07 10 15173 07 (10)R 00 07 (10)07 (10)4 07 102014 07 10 Szokująca prawda A Moritz, Szczepienia pełne kłamstwĆwiczenia I 07 10 2012Analiza Finansowa Wykład 01 07 10 09więcej podobnych podstron