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
Listing 11-1: Producing sine wave patterns with a bitmap
    interface

    const

       .

       .

       .

      {controls wave magnitude}

      MAGNITUDE = 10;

      {controls wave frequency}

      FREQUENCY = 720;

       .

       .

       .

    var

       .

       .

       .

      {the starting angle}

      AngleStart: Integer;

    implementation

       .

       .

       .

    procedure TfrmDXAppMain.FormCreate(Sender: TObject);

    begin

       .

       .

       .

      {initialize our starting angle}

      AngleStart := 0;

    end;

       .

       .

       .

    { — this method initializes DirectX and creates all necessary objects — }

    procedure TfrmDXAppMain.FormActivate(Sender: TObject);

    begin

       .

       .

       .

      {create a palette based on this bitmap}

      FPalette := DDLoadPalette(FDirectDraw, ExtractFilePath(ParamStr(0))+

                                ‘texasflag.bmp’);

      {attach the palette to the primary surface so that it takes effect}

      DXCheck( FPrimarySurface.SetPalette(FPalette) );

      {load in the bitmap containing the flag image}

      FFlag := DDLoadBitmap(FDirectDraw, ExtractFilePath(ParamStr(0))+

                            ‘texasflag.bmp’);

       .

       .

       .

    end;

       .

       .

       .

    procedure TfrmDXAppMain.DrawSurfaces;

    var

      DestSrfcInfo, FlagSrfcInfo: TDDSurfaceDesc2;

      DestPtr, FlagPtr: PByteArray;

      DestX, DestY, StartY, AngleBegin: Integer;

    begin

      {erase the last frame of animation}

      ColorFill(FBackBuffer, 0, nil);

      try

        {lock the flag surface}

        FlagSrfcInfo.dwSize := SizeOf(TDDSurfaceDesc2);

        DXCheck( FFlag.Lock(nil, FlagSrfcInfo, DDLOCK_SURFACEMEMORYPTR or

                            DDLOCK_WAIT, 0) );

        FlagPtr := PByteArray(FlagSrfcInfo.lpSurface);

        {lock the destination surface}

        DestSrfcInfo.dwSize := SizeOf(TDDSurfaceDesc2);

        DXCheck( FBackBuffer.Lock(nil, DestSrfcInfo, DDLOCK_SURFACEMEMORYPTR or

                                  DDLOCK_WAIT, 0) );

        {this positions the initial starting point of destination drawing

         so that the flag will be centered horizontally and vertically}

        DestPtr := PByteArray(integer(DestSrfcInfo.lpSurface)+

                              (DestSrfcInfo.lPitch*((DXHEIGHT div 2)-

                              (FlagSrfcInfo.dwHeight div 2)))+

                              ((DXWIDTH div 2)-(FlagSrfcInfo.dwWidth div 2)));

        {increment our starting angle. this produces the motion of the wave,

         and a larger value will make the wave move faster. a negative value

         makes the wave move from left to right; positive values reverse

         this direction. incidentally, we never have to ‘roll over’ this

         value as Sin will return a value in the range -1 to 1 for any

         argument}

        Inc(AngleStart, -5);

        {begin iterating through each vertical strip}

        for DestX := 0 to FlagSrfcInfo.dwWidth do

        begin

          {we want to add 1 to the starting angle for each column in the bitmap}

          AngleBegin := DestX+AngleStart;

          {the FREQUENCY value increases the frequency of the wave across

           the bitmap. with a value of 360, the waves will peak and valley only

           once across the entire length of the bitmap. our frequency value is

           720, which causes 2 peaks and valleys, and makes a nice effect.

           increasing or decreasing this value accordingly may simulate wind

           strength.  this value is divided by the width of the bitmap to produce

           an ‘angles-per-pixel’ ratio so that the effect will spread evenly

           across the horizontal length of the bitmap.  this value must be in

           terms of radians instead of degrees, so we must multiply it by

           (PI/180).  finally, the MAGNITUDE value scales the results and produces

           offsets, in our example, between -10 and 10. this makes the peaks appear

           higher and the valleys appear lower.}

          StartY:=Trunc((Sin(((FREQUENCY/FlagSrfcInfo.dwWidth)*AngleBegin)*

                             (PI/180))*MAGNITUDE));

          {begin drawing the vertical strip of pixels}

          for DestY := 0 to FlagSrfcInfo.dwHeight do

            {the vertical offset is added to the vertical destination value, which

             may move this column of pixels up or down}

            DestPtr[DestSrfcInfo.lPitch*(DestY+StartY)+DestX] :=

            FlagPtr[FlagSrfcInfo.lPitch*DestY+DestX];

        end;

      finally

        {release all locks}

        FFlag.Unlock(nil);

        FBackBuffer.Unlock(nil);

      end;

    end;

    end.
Alternatives/Enhancements The resulting animation from our bitmap transformation, while effective, is a little cheesy. We could produce a more realistic effect by applying another sine wave along the x-axis, perhaps at a 45-degree angle from horizontal. If we scaled the horizontal sine wave offset so that pixels moved left or right very little at the left side of the image, but they moved a large distance at the right side of the image, we could produce a more realistic wind effect. The result would make the flag look like it folded back on itself, and that it was attached to a flagpole. #### Scaling Sometimes it may be necessary to draw a bitmap image at a size other than its original dimensions. For example, we could create the illusion of a creature getting closer to the user by drawing its image larger and larger as it draws nearer. By scaling an image in this manner, we can produce the illusion of depth, or even provide zooming functionality for things like sniper scopes. Basic Theory Scaling a bitmap involves drawing the pixels of the source bitmap into the destination according to a specific ratio. This ratio determines the final size of the bitmap as it appears in the destination. The ratio is expressed as a fraction, or a floating-point number; the larger the number, the larger the bitmap, and vice versa. For example, a ratio of 2 indicates that the final bitmap will be twice as large as its original size, whereas a ratio of 0.5 indicates that the final bitmap will be half of its original size. Specifically, the ratio indicates how each pixel is mapped into the destination. If we iterate through the pixels in the destination and divide their coordinates by the scaling factor, we can determine which pixel to select from the source. This is accomplished by the following equations:
    Source_X := Trunc(Destination_X / Scale);

    Source_Y := Trunc(Destination_Y / Scale);
A scaling factor less than 1 causes pixels in the source image to be skipped, thus resulting in a smaller final image. Similarly, a scaling factor greater than 1 causes pixels in the source image to be replicated, resulting in a larger final image. The following listing demonstrates this technique.
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.