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 TApplications 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 10Logika NSA 04 1404 j 14Krasnodębski Z , 2010 04 14 Rz, Już nie przeszkadza (L Kaczyński)chemia z tutorem 3 04 14 model i odpowiedzi2005 04 14TI 99 04 14 T B M pl(1)WSM 04 14 pl(2)pdm 2015 04 14Wyklad 04 14 15 GWPlakat WEGLINIEC Odjazdy wazny od 14 04 27 do 14 06 14Nasz Dziennik 14 04 2016 (Alergia)więcej podobnych podstron