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
We can do this by setting our threshold amount to a specific time interval, measured in milliseconds. Our current interval measurement would then be set to the system time of the last increment of the frame number. In the game loop, we then check to see if the amount of time indicated in the threshold has elapsed since the last increment of the frame number. If so, we increment the frame number and reset the current interval measurement. The following example demonstrates this technique.
Listing 6-7: Accurate sprite animation timing
type
sprite class TSprite = class
FXPos, FYPos, // tracks the current position
FXVel, FYVel, // tracks the velocity
FCurFrame, // tracks the current frame number
FFrameNum: Integer; // tracks the number of frames
FImages: IDirectDrawSurface4; // a pointer to the sprite images
FCurTime, // tracks a timing value
FTimeThreshold: LongWord; // holds the animation timing threshold
end;
procedure TfrmDXAppMain.FormActivate(Sender: TObject);
var
.
.
.
begin
.
.
.
{initialize the sprite object}
FSprite := TSprite.Create;
FSprite.FXPos := DXWIDTH - 90;
FSprite.FYPos := 215;
FSprite.FXVel := -1;
FSprite.FYVel := 0;
FSprite.FCurFrame := 0;
FSprite.FFrameNum := 5;
FSprite.FImages := FImages;
{retrieve the current system time to initialize the timing algorithm}
FSprite.FCurTime := timeGetTime;
{we want the sprite to animate every 100 milliseconds}
FSprite.FTimeThreshold := 100;
.
.
.
end;
procedure TfrmDXAppMain.DrawSurfaces;
var
.
.
.
begin
{erase the last frame of animation by using a simple color fill to
black out the entire backbuffer surface}
FillChar(BltFx, SizeOf(TDDBltFx), 0);
BltFx.dwSize := SizeOf(TDDBltFx);
BltFx.dwFillColor := 0;
FBackBuffer.Blt(nil, nil, nil, DDBLT_COLORFILL or DDBLT_WAIT, @BltFx);
{increment the frame number and update the sprites position}
with FSprite do
begin
{if the elapsed time since the last frame number increment
is greater than our threshold amount...}
if timeGetTime - FCurTime > FTimeThreshold then
begin
{animate the sprite by incrementing the frame number}
Inc(FCurFrame);
{make sure we roll over the frame number as necessary}
if FCurFrame > FFrameNum then
FCurFrame := 0;
{store the current system time}
FCurTime := timeGetTime;
end;
.
.
.
end;
Z-Order
As stated above, the z-order of a sprite is its position along an imaginary third- dimensional axis. Some games may feature foreground sprites and background sprites, while others may have sprites that move closer to and farther from the user, scaling as appropriate in a pseudo three-dimensional viewpoint. In games like these, drawing sprites in the correct order becomes an important issue.
However, actually accomplishing this illusion of depth is quite simple. Essentially, the application needs to draw the sprites starting with the farthest from the user and ending with the closest. As you draw the nearer sprites, their images will obscure those farther away, giving the illusion of depth. This is known as the painters algorithm; the technique is illustrated below.
Figure 6-9: The painters algorithm
Weve already implemented the painters algorithm in a very simplistic way by drawing the background behind the sprites before drawing them. In a more complex, real-world application, the z-order of the sprites themselves must be taken into account. We can accomplish this by simply adding another member to our sprite object for tracking this z-order.
In practice, well need to move the sprites and then sort them by z-order before drawing. The sorting step is necessary in order to draw the sprites in the correct order. Any well-documented, high-performance sorting algorithm will do. In the following example, we dont employ any sort of real sorting algorithm for the sake of code simplicity. However, the example does demonstrate a simple z-ordering mechanism. Sprites that are moving downward have a higher, or closer, z-order than those moving upward. Implementing scaling to draw the sprites larger when they are closer and smaller when they are farther away would improve the illusion.
Listing 6-8: Drawing sprites according to z-order
type
.
.
.
{the sprite class}
TSprite = record
FXPos, FYPos, // tracks the current position
FXVel, FYVel, // tracks the velocity
Height, Width, // sprite frame height and width
FCurFrame, // tracks the current frame number
FFrameNum: Integer; // tracks the number of frames
FImages: IDirectDrawSurface4; // a pointer to the sprite images
FCurTime, // tracks a timing value
FTimeThreshold: LongWord; // holds the animation timing threshold
ZOrder: Integer; // the sprite depth
end;
var
.
.
.
Sprites: array[0..1] of TSprite;
ZOrderIndex: array[0..1] of Integer;
implementation
.
.
.
procedure TfrmDXAppMain.FormActivate(Sender: TObject);
begin
.
.
.
{initialize the first spaceship}
with Sprites[0] do
begin
Width := 61;
Height := 56;
FXPos := DXWIDTH div 2;
FYPos := DXHEIGHT;
FYVel := 3;
FImages := FShip1;
ZOrder := 0;
end;
{initialize the second spaceship}
with Sprites[1] do
begin
Width := 60;
Height := 74;
FXPos := DXWIDTH div 2;
FYPos := 0;
FYVel := -3;
FImages := FShip2;
ZOrder := 1;
end;
.
.
.
end;
.
.
.
procedure TfrmDXAppMain.DrawSurfaces;
var
iCount: Integer;
Area: TRect;
{this function moves a sprite}
procedure MoveSprite(var Sprite: TSprite);
begin
Sprite.FYPos := Sprite.FYPos + Sprite.FYVel;
if Sprite.FYPos<0 then
begin
Sprite.FYPos := 0;
Sprite.FYVel := 0-Sprite.FYVel;
{weve only got 2 z-order values, so flip it when the sprite
hits a boundary}
Sprite.ZOrder := 1-Sprite.ZOrder;
end
else
if Sprite.FYPos>DXHEIGHT-Sprite.Height then
begin
Sprite.FYPos := DXHEIGHT-Sprite.Height;
Sprite.FYVel := 0-Sprite.FYVel;
Sprite.ZOrder := 1-Sprite.ZOrder;
end;
end;
begin
{erase the previous animation frame}
Area := Rect(0, 0, DXWIDTH, DXHEIGHT);
FBackBuffer.BltFast(0, 0, FBackground, Area,
DDBLTFAST_NOCOLORKEY or DDBLTFAST_WAIT);
{move the sprites}
for iCount := 0 to 1 do
MoveSprite(Sprites[iCount]);
{perform some really simplistic z-order sorting}
if Sprites[0].ZOrder > Sprites[1].ZOrder then
begin
ZOrderIndex[0] := 0;
ZOrderIndex[1] := 1;
end
else
begin
ZOrderIndex[0] := 1;
ZOrderIndex[1] := 0;
end;
{now that the sprites are sorted per their z-order, draw them starting
with the farthest sprite. this will result in a layered graphic with
distant sprites being obscured by closer sprites}
for iCount := 0 to 1 do
FBackBuffer.BltFast(Sprites[ZOrderIndex[iCount]].FXPos,
Sprites[ZOrderIndex[iCount]].FYPos,
Sprites[ZOrderIndex[iCount]].FImages,
Rect(0, 0, Sprites[ZOrderIndex[iCount]].Width,
Sprites[ZOrderIndex[iCount]].Height),
DDBLTFAST_SRCCOLORKEY or 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:
terminarz roku 06 07 latoterminarz roku 06 07 zimaIII lek zagadnienia 06 07 poprTI 01 06 07 T plplan zajec semestr 3 06 07R 06 07BO 06 07 KontraktARYTM KOL2 06 07 rozwwięcej podobnych podstron