06 04


Delphi Graphics and Game Programming Exposed! with DirectX For versions 5.0-7.0:Sprite 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 Pixel Checking A somewhat more direct way of implementing transparency, this method draws the sprite image one pixel at a time. As it is drawing individual pixels, it checks the pixel it will be drawing to see if its color matches the specified transparent color. If so, it skips drawing that pixel entirely; otherwise it draws the pixel into the destination. Implementing this method is a bit more involved than color keying. By its very nature, it is pointer intensive and requires some creative pointer manipulation. It also requires more intimate knowledge of the pixel format of both the source and destination surfaces. It is slower than color keying, but through clever optimization can be as fast as non-hardware assisted color keying. However, the biggest benefit that a developer will see from this method is that it allows the creation of incredible special effects, such as lighting and translucency. Locking a Surface This method requires direct access to the memory that contains both the source bitmap and the destination, which is usually the backbuffer surface. Using normal GDI functions, this would be impossible. This is one of the things that makes DirectDraw so attractive to game developers. To retrieve a pointer to surface memory, we must use the Lock method of the IDirectDrawSurface4 object. Using this method, we can access the entire surface memory or provide the coordinates for accessing only a specific rectangular area of the memory. The Lock method is defined as: function Lock ( lpDestRect: PRect; // the surface region to lock out lpDDSurfaceDesc: TDDSurfaceDesc2; // a TDDSurfaceDesc2 structure dwFlags: DWORD; // indicates locking behavior hEvent: THandle // unused ): HResult; // returns a DirectX error code The first parameter indicates the rectangular area of the surface to lock; specifying nil in this parameter locks the entire surface. The second parameter is a TDDSurfaceDesc2 structure that will be initialized with relevant details about the surface. In particular, the lpSurface member of this structure will contain a pointer to the upper left pixel of the surface memory. Other members of this structure will contain additional information about the surface, such as its height, width, and stride. The third parameter is a series of flags controlling access to the locked memory, such as read-only or write-only. The final parameter is unused and should be set to zero. As an example, the code for retrieving a pointer to our backbuffer memory would look something like: var BackSurfaceDesc: TDDSurfaceDesc2; begin {initialize the size member} BackSurfaceDesc.dwSize := SizeOf(TDDSurfaceDesc2); {lock the backbuffer memory} FBackBuffer.Lock(nil,BackSurfaceDesc,DDLOCK_WAIT or DDLOCK_SURFACEMEMORYPTR,0) Note: It is very important to always set the size member of any record structure that has one before using it in any function call. As with all DirectX functions, it is usually a good practice to check the return code from a call to the Lock method. The DDLOCK_WAIT flag will cause the Lock method to wait until the surface is available and no longer being accessed by the hardware blitter. However, if the surface is locked by another thread or process, this function will return immediately with a DDERR_SURFACEBUSY error regardless of the DDLOCK_WAIT flag. Accessing the Memory When the Lock method returns, the lpSurface member of the TDDSurfaceDesc2 structure will contain a pointer to the surface memory. Exactly how this is used depends entirely on the pixel format of the surface. Since all of our examples deal with 256-color palettized display modes, pixels will be stored as bytes. Therefore, if we typecast the lpSurface member as a pointer to a byte, writing a value at the location reference by this pointer will change one byte on the surface, and thus one pixel in the image the surface contains. In practice, it is useful to access this pointer as a pointer to an array of bytes. This allows us to access horizontal bytes as if they were stored in a one-dimensional array. Although perhaps not immediately obvious, the process is simple. We’ll need to create a new data type that is declared as an array of byte with only one element, and another data type that is a pointer to this previous type, like so: TBytePtr = array[0..0] of Byte; PBytePtr = ^TBytePtr; Then, if we set a variable of type PBytePtr to the value of the lpSurface member, we can easily reference the surface memory as an array of bytes: var BackMem: PBytePtr; begin BackMem := PBytePtr(BackSurfaceDesc.lpSurface); Drawing the Sprite We must lock both the backbuffer surface and the surface containing the sprite images. Once this is done, we iterate through each row of the sprite, and each pixel in the row. For each pixel in the current row being drawn, we check to see if it is equal to the specified transparent color. If it is not, we go ahead and set the appropriate pixel in the destination memory to the value of the pixel being checked. If it is indeed equal to the transparent color, we simply move on to the next pixel in the row. The following example demonstrates an implementation of this technique. Listing 6-4: Drawing a sprite with transparent pixels procedure TfrmDXAppMain.DrawSurfaces; var SourceRect: TRect BackSurfaceDesc, SpriteSurfaceDesc: TDDSurfaceDesc2; BackMem, SpriteMem: PBytePtr; Row, Col: Integer; begin {erase the last frame of animation} SourceRect := Rect(0, 0, DXWIDTH, DXHEIGHT); FBackBuffer.BltFast(0, 0, FBackground, SourceRect, DDBLTFAST_NOCOLORKEY OR DDBLTFAST_WAIT); {increment the frame number and update the sprite’s position} with FSprite do begin Inc(FCurFrame); {rollover the frame number as necessary} if FCurFrame > FFrameNum then FCurFrame := 0; {add the velocities to the positions. our sprite will only move horizontally, so we do not need to bother with the vertical values} FXPos := FXPos + FXVel; {see if the sprite is moving offscreen, and adjust its position accordingly} if FXPos < 0 then FXPos := DXWIDTH - 90; {—begin blitting the current frame—} {we need to lock both the backbuffer surface and the sprite image surface, so begin by locking the backbuffer} BackSurfaceDesc.dwSize := SizeOf(TDDSurfaceDesc2); {we ’re going to lock the entire surface} DXCheck(FBackBuffer.Lock(nil, BackSurfaceDesc, DDLOCK_WAIT or DDLOCK_SURFACEMEMORYPTR, 0)); {initialize the byte array pointer to point at the locked memory} BackMem := PBytePtr(BackSurfaceDesc.lpSurface); {increment this pointer to the position in the buffer at which the sprite should be displayed (based on the sprite’s position)} BackMem := Pointer(Longint(BackMem)+FXPos+(FYPos*BackSurfaceDesc.lPitch)); {now, lock the sprite surface} SpriteSurfaceDesc.dwSize := SizeOf(TDDSurfaceDesc2); {again, we’ll lock the entire surface} DXCheck(FImages.Lock(nil, SpriteSurfaceDesc, DDLOCK_WAIT or DDLOCK_SURFACEMEMORYPTR, 0)); {initialize the byte array pointer to point at the locked memory} SpriteMem := PBytePtr(SpriteSurfaceDesc.lpSurface); {increment this pointer to the position of the current sprite frame} SpriteMem := Pointer(Longint(SpriteMem)+(FCurFrame*90)); {iterate through each row of pixels in the sprite image (our sprite image is 90 X 50)} for Row := 0 to 49 do begin {iterate through each pixel in the current row} for Col := 0 to 89 do {if the pixel in the sprite image is not 0 (the transparent color), copy it into the destination surface} if SpriteMem^[Col] <> 0 then BackMem^[Col] := SpriteMem^[Col]; {move to the next row in the sprite and backbuffer surface memory} Inc(BackMem, BackSurfaceDesc.lPitch); Inc(SpriteMem, SpriteSurfaceDesc.lPitch); end; ******************************************************************************** {we have now copied the sprite, so unlock the surface memory} FBackBuffer.Unlock(nil); FImages.Unlock(nil); 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:
egzamin96 06 04
WSM 06 04 pl
06 04 Maria Wojtak Wybrane elementy staropolskiej etykiety językowej
06 04
ZL5 06 04
Przedstawiciel władz Iraku podejrzany o malwersacje (06 04 2009)
ZL1 06 04
ZL2 06 04
ZL4 06 04
Plakat WEGLINIEC Odjazdy wazny od 14 04 27 do 14 06 14
ZADANIE A1 2009 04 06
TI 01 04 06 B pl
WSM 04 06 pl(1)

więcej podobnych podstron