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
Tip: The dwTimeStamp member of this structure indicates when the input event actually occurred. The time stamps from subsequent events could potentially be used to determine if the user double-clicked on some item. The dwSequence number, on the other hand, indicates the chronological sequence in which input events where obtained. This is useful for determining the order of input from two separate devices, as DirectInput never assigns the same sequence number for events from different devices, even if they have the same time stamp. This might come in handy if developing a multiplayer game where two people can play from the same machine.
All of this new functionality has been added to our baseline application so we can easily create DirectX applications with mouse support. While we are not going to cover it here, this new baseline application contains some additional code for drawing the mouse cursor on the primary surface from the secondary input thread. This solves the problem we noted earlier about the mouse cursor dependency on the animation frame rate. The following listing illustrates using the event notification and buffered data retrieval methods for obtaining mouse input data.
Listing 7-10: Retrieving buffered mouse input data
interface
type
.
.
.
{this class is used to track click events}
TMouseData = class
public
XPos, YPos: Integer;
Button: TMouseButton;
constructor Create(X, Y: Integer; MButton: TMouseButton);
end;
var
CurX, CurY, OldX, OldY: Integer; // the mouse position variables
MouseClickList: TList; // the list of click events
FCritSec: TCriticalSection; // syncronization object
FMouseEvents: TWOHandleArray; // events array
const
{were using a 32 X 32 pixel mouse cursor image}
CURSORWIDTH = 32;
CURSORHEIGHT = 32;
{our animated mouse cursor has 8 frames}
NUMFRAMES = 8;
implementation
constructor TMouseData.Create(X, Y: Integer; MButton: TMouseButton);
begin
{create and initialize the mouse data object for a click event}
XPos := X;
YPos := Y;
Button := MButton;
end;
procedure TMouseThread.Execute;
var
EventNum: Integer;
NumElements: DWORD;
DeviceData: TDIDeviceObjectData;
DataResult: HRESULT;
SourceRect,
DirtyRect: TRect;
begin
{continuously perform this code until terminated}
while not Terminated do
begin
{wait until one of the events becomes signaled}
EventNum := WaitForMultipleObjects(2, @FMouseEvents, FALSE, INFINITE);
{was the quit event signaled? if so, terminate}
if EventNum-WAIT_OBJECT_0 = QUITEVENT then
begin
Terminate;
Break;
end;
{we are about to use global variables, so enter the critical section}
FCritSec.Enter;
{store the current mouse cursor coordinates}
OldX := CurX;
OldY := CurY;
{begin retrieving buffered data}
while TRUE do
begin
{we only want to retrieve one element at a time}
NumElements := 1;
{retrieve the buffered data}
DataResult := FMouseDevice.GetDeviceData(SizeOf(TDIDeviceObjectData),
@DeviceData, NumElements, 0);
{if we retrieved data, update global variables}
if (DataResult = DI_OK) and (NumElements = 1) then
begin
case DeviceData.dwOfs of
{update mouse cursor positions}
DIMOFS_X : CurX := CurX + DeviceData.dwData;
DIMOFS_Y : CurY := CurY + DeviceData.dwData;
{update our list of click events}
DIMOFS_BUTTON0 : MouseClickList.Add(TMouseData.Create(CurX, CurY,
mbLeft));
DIMOFS_BUTTON1 : MouseClickList.Add(TMouseData.Create(CurX, CurY,
mbRight));
end;
end
else
{if there were no move input events to retrieve, continue}
Break;
end;
{clip the global mouse cursor positions to the extents of our
screen resolution}
if CurX < 0 then
CurX := 0;
if CurX > DXWIDTH-CURSORWIDTH then
CurX := DXWIDTH-CURSORWIDTH-1;
if CurY < 0 then
CurY := 0;
if CurY > DXHEIGHT-CURSORHEIGHT then
CurY := DXHEIGHT-CURSORHEIGHT-1;
{if the mouse position has changed...}
if not ((CurX = OldX) and (CurY = OldY)) then
begin
{draw the mouse cursor if the old and new positions do not overlap...}
if (ABS(CurX - OldX)>= CURSORWIDTH) or
(ABS(CurY - OldY)>= CURSORHEIGHT) then
begin
{erase the old cursor}
SourceRect := Rect(NUMFRAMES*CURSORWIDTH, 0, NUMFRAMES*CURSORWIDTH+
CURSORWIDTH, CURSORHEIGHT);
FPrimarySurface.BltFast(OldX, OldY, FMouseCursors, SourceRect,
DDBLTFAST_NOCOLORKEY or DDBLTFAST_WAIT);
{save area under new cursor location}
SourceRect := Rect(CurX, CurY, CurX+CURSORWIDTH, CurY+CURSORHEIGHT);
FMouseCursors.BltFast(NUMFRAMES*CURSORWIDTH, 0, FPrimarySurface,
SourceRect, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
{draw new cursor}
SourceRect := Rect(FCursorFrame*CURSORWIDTH, 0, (FCursorFrame*
CURSORWIDTH)+CURSORWIDTH, CURSORHEIGHT);
FPrimarySurface.BltFast(CurX, CurY, FMouseCursors, SourceRect,
DDBLTFAST_NOCOLORKEY or DDBLTFAST_WAIT);
end
else
{...or draw the mouse cursor if the old and new positions do overlap}
begin
{copy the dirty rectangle to the scratch buffer}
UnionRect(DirtyRect, Rect(OldX, OldY, OldX+CURSORWIDTH,
OldY+CURSORHEIGHT),
Rect(CurX, CurY, CurX+CURSORWIDTH, CurY+CURSORHEIGHT));
FMouseScratch.BltFast(0, 0, FPrimarySurface, DirtyRect,
DDBLTFAST_NOCOLORKEY or DDBLTFAST_WAIT);
{erase the old cursor from the scratch buffer}
SourceRect := Rect(NUMFRAMES*CURSORWIDTH, 0, NUMFRAMES*CURSORWIDTH+
CURSORWIDTH, CURSORHEIGHT);
FMouseScratch.BltFast(OldX-DirtyRect.Left, OldY-DirtyRect.Top,
FMouseCursors, SourceRect, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
{save the area under the new cursor}
SourceRect := Rect(CurX-DirtyRect.Left, CurY-DirtyRect.Top, (CurX-
DirtyRect.Left)+CURSORWIDTH, (CurY-
DirtyRect.Top)+CURSORHEIGHT);
FMouseCursors.BltFast(NUMFRAMES*CURSORWIDTH, 0, FMouseScratch,
SourceRect, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
{draw new cursor into scratch buffer}
SourceRect := Rect(FCursorFrame*CURSORWIDTH, 0, (FCursorFrame*
CURSORWIDTH)+CURSORWIDTH, CURSORHEIGHT);
FMouseScratch.BltFast(CurX-DirtyRect.Left, CurY-DirtyRect.Top,
FMouseCursors, SourceRect, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
{draw scratch buffer back to primary buffer}
SourceRect := Rect(0, 0, DirtyRect.Right-DirtyRect.Left,
DirtyRect.Bottom-DirtyRect.Top);
FPrimarySurface.BltFast(DirtyRect.Left, DirtyRect.Top, FMouseScratch,
SourceRect, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
end;
end;
{we are finished using global variables, so we can now leave
the critical section}
FCritSec.Leave;
end;
end;
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 (11)07 11Historia sztuki nowoczesnej polskiej malarstwo 07 11Efektywnosc2010 07 11więcej podobnych podstron