04 14


Delphi Graphics and Game Programming Exposed! with DirectX For versions 5.0-7.0:An Introduction to DirectX                       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 The DirectX Baseline Application In an effort to expedite the creation of DirectX applications, this book contains a baseline DirectX application that instantiates DirectDraw, sets up a page flipping architecture, and implements a high-speed rendering loop that can attain the highest animation speed possible. This is implemented by providing an event handler for the TApplication’s OnIdle event. The OnIdle event is called whenever the application becomes idle; if the Done parameter of this method is set to False, this event will continuously be called by the application, providing a perfect spot for a rendering loop. There are stubbed out methods for drawing surface content and restoring surface content in the event that it is lost. A number of constants are defined at the top of the main unit that control the display resolution and color depth, as well as the cooperative level and the flags for the complex flipping surface. The indicated display resolution and color depth is checked to see if it is supported before setting the display mode. It will also shut off the rendering loop automatically when the application is Alt+Tabbed out of, and restart it when Alt+Tabbed back into. Theoretically, all one must do is load off-screen surfaces in the area indicated in the Activate method, flesh out the RestoreSurfaces method to restore any off-screen surface memory, and complete the DrawSurfaces method to render animation to the backbuffer surface. The act of flipping the surfaces is carried out by the rest of the application. The Escape key will exit the application and return to Windows. Bear in mind that this is a general architecture meant to assist the reader in quickly getting a DirectX application up and running. It also provides a standardized framework from which every other example throughout the rest of this book will be based, cutting down on the amount of code that must be illustrated in example listings. This is not the best architecture for every game. Indeed, you may need to alter it dramatically depending on the requirements of your application. However, the baseline application tries to be as unimposing as possible, taking care of standard functionality while providing plenty of room for application-specific logic. What follows is a complete listing of the baseline application. Future examples will be based on this application, and thus will not contain any of the code for initializing DirectDraw; code listings will only contain code pertinent to the current discussion. This baseline application will run as is, but the output will be a black screen. However, it is a simple task to implement code in the DrawSurfaces method that will output animation to the screen, and we will see many examples of this in the coming chapters. Listing 4-7: The DirectX baseline application unit DDrawSkelU; {****************************************************************************** Skeleton DirectDraw Application Author: John Ayres This is a bare bones DirectDraw application that creates a primary surface with one backbuffer and implements a continuous flip between them. It contains some minimal error checking code as well as an application exception handling routine that flips back to the GDI surface so that exception messages can be seen. The Application.OnIdle event is used to implement the loop that flips the surfaces. This uses a large chunk of CPU time (which is ok in a game), but could potentially be replaced with a While..Do loop or some other looping architecture. This baseline code is used throughout the book as a starting point for examples. It was designed to be easily extensible, and should provide all of the initialization and startup code that you will need for your own DirectX applications. Code that is marked by ‘///’ can and should be replaced by your own code. ****************************************************************************** Copyright © 1999 by John Ayres, All Rights Reserved This code is freeware and can be used for any personal or commercial purposes without royalty or license. Use at your own risk. ******************************************************************************} interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, DDraw; {these constants are used to modify specific attributes of the DirectX application, such as the resolution and color depth} const DXWIDTH = 640; DXHEIGHT = 480; DXCOLORDEPTH = 8; BUFFERCOUNT = 1; COOPERATIVELEVEL = DDSCL_FULLSCREEN or DDSCL_ALLOWREBOOT or DDSCL_ALLOWMODEX or DDSCL_EXCLUSIVE; SURFACETYPE = DDSCAPS_COMPLEX or DDSCAPS_FLIP or DDSCAPS_PRIMARYSURFACE; const {this user-defined message is used to start the flipping loop} WM_DIRECTXACTIVATE = WM_USER + 200; type TfrmDXAppMain = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormActivate(Sender: TObject); private { Private declarations } {flips back to the GDI surface to display the exception error message} procedure ExceptionHandler(Sender: TObject; ExceptionObj: Exception); {the main rendering loop} procedure AppIdle(Sender: TObject; var Done: Boolean); {intercepts certain messages to provide appropriate functionality} procedure AppMessage(var Msg: TMsg; var Handled: Boolean); {flips the DirectDraw surfaces} procedure FlipSurfaces; {restores any lost surfaces} procedure RestoreSurfaces; {draws the contents of surfaces} procedure DrawSurfaces; public { Public declarations } end; var frmDXAppMain: TfrmDXAppMain; {the main DirectDraw interface} FDirectDraw: IDirectDraw4; {the interfaces for the primary and backbuffer surfaces} FPrimarySurface, FBackBuffer: IDirectDrawSurface4; implementation uses DXTools; {$R *.DFM} { *–->> BASELINE APPLICATION CODE <<–-* } { – the callback function used to ensure that the selected graphics – – mode is supported by DirectX – } function EnumModesCallback(const EnumSurfaceDesc: TDDSurfaceDesc2; Information: Pointer): HResult; stdcall; begin {if the height, width, and color depth match those specified in the constants, then indicate that the desired graphics mode is supported} if (EnumSurfaceDesc.dwHeight = DXHEIGHT) and (EnumSurfaceDesc.dwWidth = DXWIDTH) and (EnumSurfaceDesc.ddpfPixelFormat.dwRGBBitCount = DXCOLORDEPTH) then Boolean(Information^) := TRUE; Result := DDENUMRET_OK; end; { –> Events hooked to the application <– } { – this event is called when an exception occurs, and simply flips back – – to the GDI surface so that the exception dialog box can be read – } procedure TfrmDXAppMain.ExceptionHandler(Sender: TObject; ExceptionObj: Exception); begin {disconnect the OnIdle event to shut off the rendering loop} Application.OnIdle := nil; {if the DirectDraw object was successfully created, flip to the GDI surface} if Assigned(FDirectDraw) then FDirectDraw.FlipToGDISurface; {display the exception message} MessageDlg(ExceptionObj.Message, mtError, [mbOK], 0); {reconnect the OnIdle event to reenter the rendering loop} Application.OnIdle := AppIdle; end; { – this method is continuously called by the application, and provides – – the main rendering loop. this could be replaced by a custom – – while..do loop – } procedure TfrmDXAppMain.AppIdle(Sender: TObject; var Done: Boolean);begin {indicates that the application should continuously call this method} Done := FALSE; {if DirectDraw has not been initialized, exit} if not Assigned(FDirectDraw) then Exit; {note that at this point game logic could be inserted that controls things like sprite movement and collision detection} {draw surface content and flip the surfaces} DrawSurfaces; FlipSurfaces; end; { – handles certain messages that are required to make DirectX function – – properly within Delphi – } procedure TfrmDXAppMain.AppMessage(var Msg: TMsg; var Handled: Boolean); begin case Msg.Message of WM_ACTIVATEAPP: {unhook the OnIdle event when the application is being deactivated. this will stop all rendering} if not Boolean(Msg.wParam) then Application.OnIdle := nil else {upon activating the application, send ourselves the user- defined message} PostMessage(Application.Handle, WM_DIRECTXACTIVATE, 0, 0); WM_DIRECTXACTIVATE: begin {upon activating, restore all surfaces (reloading their memory as necessary), hook up the OnIdle event, and redraw the contents of all surfaces} RestoreSurfaces; Application.OnIdle := AppIdle; DrawSurfaces; end; WM_SYSCOMMAND: begin {do not allow a screen saver to kick in} Handled := (Msg.wParam = SC_SCREENSAVE); end; end; end; { –> Form Events <– } { – initialize essential form properties – } procedure TfrmDXAppMain.FormCreate(Sender: TObject); begin {set up the application exception handler} Application.OnException := ExceptionHandler; {initialize form properties. note that the FormStyle property must be set to fsStayOnTop} BorderStyle := bsNone; BorderIcons := []; FormStyle := fsStayOnTop; Color := clBlack; Cursor := crNone; {turn off the mouse cursor} ShowCursor(FALSE); end; { – provides essential cleanup functionality – } procedure TfrmDXAppMain.FormDestroy(Sender: TObject); begin {disengage our custom exception handler} Application.OnException := nil; {display the mouse cursor} ShowCursor(TRUE); {remember, we do not have to explicitly free the DirectX objects, as they will free themselves when they go out of context (such as when the application is closed)} end; { – this method initializes DirectX and creates all necessary objects – } procedure TfrmDXAppMain.FormActivate(Sender: TObject); var {we can only get a DirectDraw4 interface from the DirectDraw interface, so we need a temporary interface} TempDirectDraw: IDirectDraw; {structures required for various methods} DDSurface: TDDSurfaceDesc2; DDSCaps: TDDSCaps2; {flag used to determine if the desired graphics mode is supported} SupportedMode: Boolean; begin {if DirectDraw has already been initialized, exit} if Assigned(FDirectDraw) then exit; {create a temporary DirectDraw object. this is used to create the desired DirectDraw4 object} DXCheck( DirectDrawCreate(nil, TempDirectDraw, nil) ); try {we can only get a DirectDraw4 interface through the QueryInterface method of the DirectDraw object} DXCheck( TempDirectDraw.QueryInterface(IID_IDirectDraw4, FDirectDraw) ); finally {now that we have the DirectDraw4 object, the temporary DirectDraw object is no longer needed} TempDirectDraw := nil; end; {hook up the application message handler} Application.OnMessage := AppMessage; {call EnumDisplayModes and verify that the desired graphics mode is indeed supported} FillChar(DDSurface, SizeOf(TDDSurfaceDesc2), 0); DDSurface.dwSize := SizeOf(TDDSurfaceDesc2); DDSurface.dwFlags := DDSD_HEIGHT or DDSD_WIDTH or DDSD_PIXELFORMAT; DDSurface.dwHeight := DXHEIGHT; DDSurface.dwWidth := DXWIDTH; DDSurface.ddpfPixelFormat.dwSize := SizeOf(TDDPixelFormat_DX6); DDSurface.ddpfPixelFormat.dwRGBBitCount := DXCOLORDEPTH; SupportedMode := FALSE; DXCheck( FDirectDraw.EnumDisplayModes(0, @DDSurface, @SupportedMode, EnumModesCallback) ); {if the desired graphics mode is not supported by the DirectX drivers, display an error message and shut down the application} if not SupportedMode then begin MessageBox(Handle, PChar(The installed DirectX drivers do not support a ‘+ ‘display mode of: ’+IntToStr(DXWIDTH)+‘ X ’+ IntToStr(DXHEIGHT)+’, ‘+IntToStr(DXCOLORDEPTH)+’ bit color‘), Unsupported Display Mode Error’, MB_ICONERROR or MB_OK); Close; Exit; end; {set the cooperative level to that defined in the constants} DXCheck( FDirectDraw.SetCooperativeLevel(Handle, COOPERATIVELEVEL) ); {set the display resolution and color depth to that defined in the constants} DXCheck( FDirectDraw.SetDisplayMode(DXWIDTH, DXHEIGHT, DXCOLORDEPTH, 0, 0) ); {initialize the DDSurface structure to indicate that we will be creating a complex flipping surface with one backbuffer} FillChar(DDSurface, SizeOf(TDDSurfaceDesc2), 0); DDSurface.dwSize := SizeOf(TDDSurfaceDesc2); DDSurface.dwFlags := DDSD_CAPS or DDSD_BACKBUFFERCOUNT; DDSurface.ddsCaps.dwCaps := SURFACETYPE; DDSurface.dwBackBufferCount := BUFFERCOUNT; {create the primary surface object} DXCheck( FDirectDraw.CreateSurface(DDSurface, FPrimarySurface, nil) ); {indicate that we want to retrieve a pointer to the backbuffer (the surface immediately behind the primary surface in the flipping chain) } FillChar(DDSCaps, SizeOf(TDDSCaps2), 0); DDSCaps.dwCaps := DDSCAPS_BACKBUFFER; {retrieve the surface} DXCheck( FPrimarySurface.GetAttachedSurface(DDSCaps, FBackBuffer) ); {at this point, offscreen buffers and other surfaces should be created. other DirectDraw objects should be created and initialized as well, such as palettes. the contents of all offscreen surfaces should also be initialized at this point} {post a message that will hook up the OnIdle event and start the main rendering loop} PostMessage(Handle, WM_ACTIVATEAPP, 1, 0); end; { –> Form Methods <– } { – this method is called in order to flip the surfaces – } procedure TfrmDXAppMain.FlipSurfaces; var DXResult: HResult; begin {perform the page flip. note that the DDFLIP_WAIT flag has been used, indicating that the function will not return until the page flip has been performed. this could be removed, allowing the application to perform other processing until the page flip occurs. however, the application will need to continuously call the Flip method to ensure that the page flip takes place} DXResult := FPrimarySurface.Flip(nil, DDFLIP_WAIT); {if the surfaces were lost, restore them. on any other error, raise an exception} if DXResult = DDERR_SURFACELOST then RestoreSurfaces else if DXResult <> DD_OK then DXCheck(DXResult); end; { – this method is called when the surface memory is lost – – and must be restored. surfaces in video memory that – – contain bitmaps must be reinitialized in this function – } procedure TfrmDXAppMain.RestoreSurfaces; begin {restore the primary surface, which in turn restores any implicit surfaces} FPrimarySurface._Restore; {here you should reload any bitmaps stored in video memory surfaces} end; { – this method is called when the contents of the surfaces need to be – – drawn. it will be continuously called by the AppIdle method, so any – – rendering or animation could be done within this method – } procedure TfrmDXAppMain.DrawSurfaces; begin end; { –> Deletable Events <– } /// { – as a matter of convenience this framework will terminate when the – – Escape key is pressed, but this should probably be deleted and – – replaced with your own terminate methods – } procedure TfrmDXAppMain.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_ESCAPE then Close; end; /// { *–->> END BASELINE APPLICATION CODE <<–-* } 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:
04 14 10
Logika NSA 04 14
04 j 14
Krasnodębski Z , 2010 04 14 Rz, Już nie przeszkadza (L Kaczyński)
chemia z tutorem 3 04 14 model i odpowiedzi
2005 04 14
TI 99 04 14 T B M pl(1)
WSM 04 14 pl(2)
pdm 2015 04 14
Wyklad 04 14 15 GW
Plakat WEGLINIEC Odjazdy wazny od 14 04 27 do 14 06 14
Nasz Dziennik 14 04 2016 (Alergia)

więcej podobnych podstron