Search Tips Advanced Search |
| 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 Illusion of Motion Creating the illusion of animation was simple enough. However, even the most complex and beautifully rendered animation would quickly get boring if it stayed in the same spot. So, how do we go about moving the animated sprite across the screen to produce a more interesting and believable animation? Again, the process is quite simple. On the most primitive level, when the application prepares to draw the next frame of animation, simply change the horizontal or vertical coordinate (or both) at which the image will be drawn into the destination. If these coordinates keep changing, the animated image will be drawn at different positions, creating the illusion of motion. #### Sprite Attributes Before we begin, a few items of information need to be tracked for each sprite. In particular, its current X (horizontal) and Y (vertical) coordinate must be tracked so the application knows where to draw the sprite. A horizontal and vertical velocity could also be stored. These velocities would indicate the number of pixels to move the sprite, and would be added to the X and Y coordinates on each iteration through the game loop. If we also tracked the current frame of animation, the number of frames in the animation, and a pointer to the bitmap or DirectDraw surface containing the sprite images, we could create a basic sprite object that might look like this:
    TSprite = class

      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

    end;
#### The Animation Cycle The effect we want to produce is the image of an object moving across the screen in a believable manner. To achieve this illusion of motion, we will tackle the process of animation by breaking it into three distinct steps: erasing the sprite image, updating the sprite position, and drawing the sprite image. If we simply move the sprite and continue to draw it on the screen without ever erasing it, the previous sprite images will still be visible, ruining the animation effect. We want our animation to look like a single object moving about as one would expect to see in a cartoon or movie. Thus, the first thing we must do is erase the previous sprite image. For this example, we will simply clear the entire surface by performing a color fill using the Blt method. The IDirectDrawSurface4’s Blt method is defined as:
    function Blt(

    lpDestRect: PRect;                    // the destination rectangle

    lpDDSrcSurface: IDirectDrawSurface4;  // the source surface

    lpSrcRect: PRect;                     // the source rectangle

    dwFlags: DWORD;                       // control flags

    lpDDBltFx: PDDBltFX                   // a pointer to a TDDBltFX structure

    ): HResult;                           // returns a DirectX error code
The first parameter describes the rectangular area in the destination surface to which the image data is copied. The second parameter identifies the surface whose image data is being copied. The third parameter describes the rectangular area in the source surface from which the image data is copied. Note that if these rectangular areas are not the same size, the resulting image will be scaled as required. The fourth parameter is a series of flags indicating which members of the final parameter are valid and generally control the behavior of the blit. The final parameter is a pointer to a TDDBltFX structure. This rather large and complex structure contains information for various special graphical effects, such as color fills and raster operations. We’ll see an example of this function’s use to perform a color fill in Listing 6-2.
| Note: In the DDUtil unit, we’ve created a function called ColorFill that uses the Blt method to fill a region with a color. You specify a surface, the color in the form of a TColor, and a rectangular region to be filled (or nil to fill the entire surface). This allows the developer to fill an area with a solid color using only one line of code.
Figure 6-4: The animation cycle Next, we simply add the horizontal and vertical velocities to the horizontal and vertical coordinates of the sprite. At this point, we may do some simple calculations to see if the sprite has moved off screen or out of bounds, and adjust its velocities accordingly. We then increment the frame number and draw the appropriate frame of the sprite image at the new coordinates. Figure 6-4 illustrates this process. The value of the sprite velocities should take into account the type of animation being performed. If the animation is a top-down view of a ship flying in space, the horizontal and vertical velocities could be adjusted to make the sprite move all around the screen. However, if the animation is a side view of a walking character, we would probably only want to adjust the horizontal velocity (unless, of course, the character is jumping). The velocity value must also be adjusted to make the animation look more believable (i.e., a character would move faster when running than when walking). Implementing this animation method is little more than an extension of the previous frame animation example, as the following listing demonstrates. Listing 6-2: Simple sprite movement
    procedure TfrmDXAppMain.DrawSurfaces;

    var

      SourceRect: TRect

      SrfcDC: HDC;

      TempCanvas: TCanvas;

      BltFx: TDDBltFx;

    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 sprite’s position}

      with FSprite do

      begin

        Inc(FCurFrame);

        {make sure we roll over 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;

        {blit the current frame}

        SourceRect := Rect(FCurFrame*90, 0, (FCurFrame*90)+90, 49);

        FBackBuffer.BltFast(FXPos, FYPos, FImages, SourceRect,

                            DDBLTFAST_SRCCOLORKEY OR DDBLTFAST_WAIT);

      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.