11 10


Delphi Graphics and Game Programming Exposed! with DirectX For versions 5.0-7.0:Special Effects                       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 Fire The fire effect is a really cool trick that, when performed properly, can create a very convincing illusion of fire. This effect is well documented both on the Web and in various books on graphics programming, and has been around for quite some time. It is a very computationally intensive effect, but it can be highly optimized and runs quite fast when implemented in assembly code. There are numerous ways of implementing this effect, but we’ll examine one that produces a nice effect at decent speeds. Basic Theory The first thing we need to accomplish is creating an appropriate palette. For an effective fire, we’ll create a palette that ranges from white in the upper slots (255-192), through yellow and orange, to red, and finally to black in the lowest slots (63-0). We could adjust the palette range somewhat and put some blues in, to simulate a cooler flame, or perhaps add some grays at the end, which would effectively simulate smoke. This effect involves moving pixels that already exist in a surface. Therefore, we need to create a new surface that will contain the image of the fire. Since we’ll be reading values from this surface, we’ll place it in system memory. This algorithm is a CPU hog, so even though we’ll create a surface that’s the same size as the screen, we’ll only use a small part of it for the effect. In our example, we’ve defined a starting and ending vertical position as well as a starting and ending horizontal position, which will confine the effect to the rectangle defined by these coordinates. Now for the real work. Starting at the first row of pixels (defined by our starting vertical position) in the fire effect surface, we begin iterating through each column (as defined by our starting and ending horizontal position). We retrieve the current value of this pixel, subtract a random amount from this number, and then place the new value in the row of pixels above our current row. In effect, this produces an animation of pixels moving upwards on the screen. Additionally, we add a random number between –1 and 1 to move the pixels left or right in a chaotic manner. Figure 11-13:  Flaming pixels Relative to the colors we defined in our palette, the pixel colors will slowly move from white, through yellow and red, and finally to black as they move upward due to the subtraction of a random value from their current color. This produces a very effective illusion of flames. At each frame of the animation, we’ll need to place some random pixel values on the bottom row of the effect to give the algorithm some starting values. Implementing this effect is very simple, as illustrated by the following example. Listing 11-8: The flame effect const . . . {define the rectangular area for the effect} XSTART = 200; XEND = 440; YSTART = 100; YEND = 400; {define the random decay value} DECAY = 6; type . . . TBytePtr = array[0..0] of Byte; PBytePtr = ^TBytePtr; var . . . {the interfaces for the primary and backbuffer surfaces} FPrimarySurface, FBackBuffer, FireSurface: IDirectDrawSurface4; {the palette interface} FPalette: IDirectDrawPalette; implementation . . . procedure TfrmDXAppMain.FormActivate(Sender: TObject); var . . . {hold the palette colors} PalColors: TColorTable; iCount: Integer; {this procedure stuffs the RGB values into the appropriate color table entry} procedure SetPalEntry(Idx, Red, Green, Blue: Integer); begin PalColors[Idx].R := Red; PalColors[Idx].G := Green; PalColors[Idx].B := Blue; PalColors[Idx].A := 0; end; begin . . . {define the colors for the palette. this will produce a spread from white to yellow/orange to red, fading to black} for iCount := 0 to 63 do begin SetPalEntry(iCount, iCount shl 2, 0, 0); SetPalEntry(64+iCount, 255, iCount shl 2, 0); SetPalEntry(128+iCount, 255, 255, iCount shl 2); SetPalEntry(192+iCount, 255, 255, 255); end; {create the actual palette} FDirectDraw.CreatePalette(DDPCAPS_8BIT or DDPCAPS_ALLOW256, @PalColors, FPalette, nil); {attach the palette to the primary surface} FPrimarySurface.SetPalette(FPalette); {create the offscreen buffer for the fire. we’re going to be modifying this constantly, so we’ll place it in system memory} FillChar(DDSurface, SizeOf(TDDSurfaceDesc2), 0); DDSurface.dwSize := SizeOf(TDDSurfaceDesc2); DDSurface.dwFlags := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH; DDSurface.dwWidth := DXWIDTH; DDSurface.dwHeight := DXHEIGHT; DDSurface.ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN or DDSCAPS_SYSTEMMEMORY; {initialize the surface} DXCheck( FDirectDraw.CreateSurface(DDSurface, FireSurface, nil) ); {initialize the offscreen buffer to all black} ColorFill(FireSurface, 0, nil); . . . end; . . . procedure TfrmDXAppMain.DrawSurfaces; var SrcRect: TRect; SrfcDesc: TDDSurfaceDesc2; iCol, iRow: Integer; FireSrfcPtr, BottomLine: PBytePtr; CurPixel: Byte; begin {begin by locking the fire surface buffer} FillChar(SrfcDesc, SizeOf(TDDSurfaceDesc2), 0); SrfcDesc.dwSize := SizeOf(TDDSurfaceDesc2); FireSurface.Lock(nil, SrfcDesc, DDLOCK_WAIT, 0); FireSrfcPtr := PBytePtr(Longint(SrfcDesc.lpSurface)+ (YSTART*SrfcDesc.lPitch)); {we’ll also need a pointer to the bottom line of the rectangular area for the effect} BottomLine := PBytePtr(Longint(SrfcDesc.lpSurface)+(YEND*SrfcDesc.lPitch)); {initialize some new pixels in the fire} for iCol := XSTART to XEND do BottomLine^[iCol] := 255-Random(32); {perform the actual flame calculations} for iRow := YSTART to YEND do begin for iCol := XSTART to XEND do begin {retrieve the pixel from this column} CurPixel := FireSrfcPtr^[iCol]; {if the pixel is less than the decay value or is at the far ends of the effect area, blacken it out...} If (CurPixel < Decay) or (iCol = XSTART) or (iCol = XEND) then {draw a black pixel on the row above the current one} PBytePtr(Longint(FireSrfcPtr)-SrfcDesc.lPitch)^[iCol] := 0 else {...otherwise, draw a new pixel on the row above the current one, either directly above or to either side of the current pixel, but subtract a random value from its color. this causes the color of the pixel to slowly move from white, through yellow and red, to black} PBytePtr(Longint(FireSrfcPtr)-SrfcDesc.lPitch)^[iCol+Random(3)-1] := CurPixel - Random(DECAY); end; {move to the next row in the fire surface} Inc(FireSrfcPtr, SrfcDesc.lPitch); end; {unlock the buffer} FireSurface.Unlock(nil); {finally, blit the fire surface to the back buffer to make it visible} SrcRect := Rect(0, 0, DXWIDTH, DXHEIGHT); FBackBuffer.BltFast(0, 0, FireSurface, SrcRect, DDBLTFAST_WAIT); 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:
Analiza Wykład 8 (25 11 10)
5 11 10 18 07 26 47
HIE 29 11 10
11 10 Lift and Drag on Road Vehicles
141 11 (10)
11 10 Luty 1998 Polacy wolni

więcej podobnych podstron