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
Basic Theory
Each transition effect may be implemented in wildly differing ways or with only subtle, minor differences, depending on the desired effect. In this example, lets use three simple effects that are relatively easy to implement yet provide cool animation effects. Specifically, these transition effects will be melt, crawl, and dissolve.
Melt This is the classic melting screen effect made popular by id softwares Doom. It works by first drawing the next scene image to the back buffer, and then drawing the closing scene one column at a time into the back buffer. An array of integers, one entry per column of pixels, is used to track the vertical offset of the start of the pixel column. By starting some columns before others, we can create the illusion of the foreground screen melting away to reveal the next scene.
Figure 11-5: The melt effect
Crawl This is a variation of the dissolve effect below. Starting from one side of the screen, we use two variables to track a beginning and ending column (or row), spaced some arbitrary distance apart. At each frame of the animation, we increment both the beginning and ending columns (or rows). These define an area into which several pixels from the next scene are drawn. Their coordinates are chosen at random and copied into the back buffer at the same position. Past the ending column (or row), the exposed portion of the next scene is drawn. The effect appears to eat away at the foreground image, revealing the image of the next scene underneath.
Figure 11-6: The crawl effect
Dissolve This is a common effect that makes one image appear to dissolve, revealing the image beneath it. It works by randomly choosing a pixel from the next image and copying it to the back buffer (over the previous image) at the same position. However, it is rather slow to use the entire screen area for the range of random pixel selection. Thus, we constrain the random pixel selection to an 8 × 8 pixel area, and then replicate that throughout the entire image. In other words, the screen is divided into 8×8 blocks. The next pixel is chosen from the first 8×8 area, and we use this coordinate as an offset for each 8×8 block throughout the screen. This creates a fast, effective dissolve effect.
Figure 11-7: The dissolve effect
The following listing demonstrates a simple implementation of these three effects. Press the spacebar to move from one image to the next.
Listing 11-5: Transition effects
interface
.
.
.
type
TTransitionType = (transMelt, transCrawl, transDissolve);
.
.
.
var
.
.
.
{holds the scene images}
ScreenBackgrounds: array[0..2] of IDirectDrawSurface4;
{tracks which background image is used next}
NextBackground: Integer;
{tracks the next transition effect to be used}
NextTransition: TTransitionType;
implementation
.
.
.
procedure TfrmDXAppMain.FormCreate(Sender: TObject);
begin
.
.
.
{initialize the next background}
NextBackground := 0;
{initialize the next transition effect}
NextTransition := transMelt;
NextTransition := transMelt;
end;
.
.
.
procedure TfrmDXAppMain.FormActivate(Sender: TObject);
begin
.
.
.
{load the palette}
FPalette := DDLoadPalette(FDirectDraw, ExtractFilePath(ParamStr(0))+
begin.bmp);
{set the palette}
FPrimarySurface.SetPalette(FPalette);
{load the three images to be used in the transition effect animations}
ScreenBackgrounds[0] := DDLoadBitmap(FDirectDraw, ExtractFilePath(
ParamStr(0))+begin.bmp);
ScreenBackgrounds[1] := DDLoadBitmap(FDirectDraw, ExtractFilePath(
ParamStr(0))+middle.bmp);
ScreenBackgrounds[2] := DDLoadBitmap(FDirectDraw, ExtractFilePath(
ParamStr(0))+end.bmp);
{copy the first image to the screen}
DestRect := Rect(0, 0, DXWIDTH, DXHEIGHT);
FPrimarySurface.BltFast(0, 0, ScreenBackgrounds[0], DestRect,
DDBLTFAST_NOCOLORKEY OR DDBLTFAST_WAIT);
FBackBuffer.BltFast(0, 0, ScreenBackgrounds[0], DestRect,
DDBLTFAST_NOCOLORKEY OR DDBLTFAST_WAIT);
.
.
.
end;
.
.
.
procedure TfrmDXAppMain.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key = VK_ESCAPE then
Close;
{if the spacebar was pressed...}
if Key = Ord( ) then
begin
{move to the next transition}
NextTransition := Succ(NextTransition);
{rollover the transition effect if necessary}
if Ord(NextTransition) > Ord(transDissolve) then
NextTransition := transMelt;
{perform the transition effect}
CoolScreenTransition(NextTransition);
end;
end;
procedure TfrmDXAppMain.CoolScreenTransition(TransitionType: TTransitionType);
var
HeadCol, TailCol: Integer;
iCount, iCount2, iCount3: Integer;
Block, DestRect: TRect;
RandBlock, RandBlock2: Integer;
Worms: array[0..DXWIDTH-1] of Integer;
StillGoing: Boolean;
begin
{move to the next image}
Inc(NextBackground);
{rollover the image index, if necessary}
if NextBackground > 2 then
NextBackground := 0;
{copy the foreground image into the back buffer}
DestRect := Rect(0, 0, DXWIDTH, DXHEIGHT);
FBackbuffer.BltFast(0, 0, FPrimarySurface, DestRect, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
case TransitionType of
transMelt : begin
{initialize the starting offsets for each column of
pixels}
for iCount := 0 to DXWIDTH-1 do
Worms[iCount] := 0;
{initialize the loop variable}
StillGoing := TRUE;
{begin the effect}
while StillGoing do
begin
{assume that the effect will stop}
StillGoing := FALSE;
{for each column of pixels...}
for iCount := 0 to DXWIDTH-1 do
begin
{if this column has not yet started to move...}
if Worms[iCount] = 0 then
{...give the column a 25% chance of starting}
if Random(4) = 1 then
Worms[iCount] := 1;
{if this column has not yet reached to bottom,
but is in motion...}
if (Worms[iCount]<DXHEIGHT-1)and(Worms[iCount]>0) then
begin
{...there is still at least one column still
alive, so the effect has not yet stopped}
StillGoing := TRUE;
{copy this column of pixels into its new position}
Block := Rect(iCount, Worms[iCount], iCount+1,
DXHEIGHT-3);
FBackBuffer.BltFast(iCount, Worms[iCount]+3,
FBackBuffer, Block,
DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
{copy the same column from the next scene above
the currently moving column}
Block := Rect(iCount, 0, iCount+1, Worms[iCount]+3);
FBackBuffer.BltFast(iCount, 0,
ScreenBackgrounds[NextBackground],
Block, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
{move the column down a bit}
Worms[iCount] := Worms[iCount]+3;
end;
end;
{the back buffer now contains the next frame of the
animation, so copy it to the screen}
DestRect := Rect(0, 0, DXWIDTH, DXHEIGHT);
FPrimarySurface.BltFast(0, 0, FBackbuffer, DestRect,
DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
end;
{the animation is over, so copy the final image to both
the front and back buffers to erase the last remains of
the animation sequence}
Block := Rect(0, 0, DXWIDTH, DXHEIGHT);
FBackbuffer.BltFast(0, 0,
ScreenBackgrounds[NextBackground],
Block, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
FPrimarySurface.BltFast(0, 0,
ScreenBackgrounds[NextBackground],
Block, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
end;
transCrawl : begin
{begin tracking the beginning and ending columns}
HeadCol := 0;
TailCol := -10;
{while the ending column is still on the screen...}
while TailCol < (DXWIDTH div 5)-1 do
begin
{iterate through the columns of pixels between the
beginning and ending column}
for iCount := TailCol to HeadCol do
{if this column is on the screen...}
if iCount > -1 then
for iCount2 := 0 to 20 do
begin
{choose a random block of pixels}
RandBlock := Random(DXHEIGHT div 5);
{copy this block of pixels from the next image
into the destination at the same coordinates}
Block := Rect(5*iCount, 5*RandBlock, 5*iCount+5,
5*RandBlock+5);
FBackBuffer.BltFast(Block.Left, Block.Top,
ScreenBackgrounds[NextBackground],
Block, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
end;
{if the ending column is on the screen...}
if TailCol > -1 then
begin
{make sure we copy the entire column of pixels from
the next image into the destination so that the
final image will be complete}
Block := Rect(5*TailCol, 0, 5*TailCol+5, DXHEIGHT);
FBackBuffer.BltFast(Block.Left, Block.Top,
ScreenBackgrounds[NextBackground],
Block, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
end;
{increment the beginning and ending columns}
Inc(HeadCol);
Inc(TailCol);
{copy this frame of animation to the screen}
Block := Rect(0, 0, DXWIDTH, DXHEIGHT);
FPrimarySurface.BltFast(0, 0, FBackbuffer, Block,
DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
{pause for a short period}
Sleep(20);
end;
{the animation is over, so copy the final image to both
the front and back buffers to erase the last remains of
the animation sequence}
Block := Rect(0, 0, DXWIDTH, DXHEIGHT);
FBackbuffer.BltFast(0, 0,
ScreenBackgrounds[NextBackground],
Block, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
FPrimarySurface.BltFast(0, 0,
ScreenBackgrounds[NextBackground],
Block, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
end;
transDissolve : begin
{we will copy 100 blocks of pixels for this effect}
for iCount := 0 to 100 do
begin
{choose a random block of pixels from our 8×8 area}
RandBlock := Random(8);
RandBlock2 := Random(8);
{this will be mirrored throughout the screen relative
to each segmented 8×8 block of pixels}
for iCount2 := 0 to 15 do
for iCount3 := 0 to 12 do
begin
{copy the relative block of pixels from the
next image into the back buffer}
Block := Rect((5*RandBlock)+(iCount2*8*5),
(5*RandBlock2)+(iCount3*8*5),
(5*RandBlock)+(iCount2*8*5)+5,
(5*RandBlock2)+(iCount3*8*5)+5);
FBackBuffer.BltFast(Block.Left, Block.Top,
ScreenBackgrounds[NextBackground],
Block, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
end;
{copy this frame of animation to the screen}
Block := Rect(0, 0, DXWIDTH, DXHEIGHT);
FPrimarySurface.BltFast(0, 0, FBackbuffer, Block,
DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
{pause for a short period}
Sleep(20);
end;
{the animation is over, so copy the final image to both
the front and back buffers to erase the last remains of
the animation sequence}
Block := Rect(0, 0, DXWIDTH, DXHEIGHT);
FBackbuffer.BltFast(0, 0,
ScreenBackgrounds[NextBackground],
Block, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
FPrimarySurface.BltFast(0, 0,
ScreenBackgrounds[NextBackground],
Block, DDBLTFAST_NOCOLORKEY or
DDBLTFAST_WAIT);
end;
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:
11 06 2 MIĘDZY TEORIĄ A PRAKTYKĄ2010 11 06 WIL Wyklad 06więcej podobnych podstron