Tricks of the Windows Game Programming Gurus:Advanced DirectDraw and Bitmapped Graphics

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

#### Using the Blitter (Finally!)

Now that you have the preliminaries out of the way, blitting an offscreen surface to any other surface is a snap. Here’s how. Assume that you’ve created a 64×64-pixel 8-bit color surface image with color index 0 as the transparent color, or something like this:

    DDSURFACEDESC2 ddsd;               // working description

    LPDIRECTDRAWSURFACE4 lpdds_image;  // temporary surface

    // initialize structure

    DDRAW_INIT_STRUCT(ddsd);

    // set to access caps, width, and height

    ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CKSRCBLT;

    // set dimensions of the new bitmap surface

    ddsd.dwWidth  =  64;

    ddsd.dwHeight =  64;

    // set surface to offscreen plain

    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | mem_flags;

    // set the color key fields

    ddsd.ddckCKSrcBlt.dwColorSpaceLowValue  = 0;

    ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0;

    // create the surface

    if (FAILED(lpdd->CreateSurface(&ddsd,&lpdds_image,NULL)))

       return(NULL);

Next, imagine that you have both a primary surface, `lpddsprimary`, and a back buffer surface, `lpddsback`, and that you want to blit the surface `lpdds_image` to the back buffer at location (x,y) with the source color key you set. Here’s how:

    // fill in the destination rect

    dest_rect.left   = x;

    dest_rect.top    = x;

    dest_rect.right  = x+64-1;

    dest_rect.bottom = y+64-1;

    // fill in the source rect

    source_rect.left    = 0;

    source_rect.top     = 0;

    source_rect.right   = 64-1;

    source_rect.bottom  = 64-1;

    // blt to destination surface

    if (FAILED(lpddsback->Blt(&dest_rect, lpdds_image,

              &source_rect,

              (DDBLT_WAIT | DDBLT_KEYSRC),

              NULL)))

        return(0);

That’s it, baby! Notice the flag `DDBLT_KEYSRC`. You must have this in the blit call, or else the color key won’t work even though there is one defined by the surface.

> Warning: When you’re blitting remember to watch out for clipping. Not setting a clipping region to the destination surface and blitting beyond it would be very bad. But all you have to do is make a call to your function `DDraw_Attach_Clipper()` and set a single clipping `RECT` that’s identical to the bounds of the screen.

At long last, you’re ready for a reasonably cool demo. Figure 7.30 is a screen shot of `DEMO7_13.CPP|EXE`. Looks cool, huh? What I’ve decided to do is add a little game programming so you can get more out of this demo than just some moving bitmaps. Basically, the demo loads in a large background bitmap and a number of frames of animation for an alien. The large background is copied to the back buffer each frame, along with a number of replicated and animated copies of the alien (which are surfaces). The aliens are then animated and moved at various velocities. See if you can add a player that’s controlled by the keyboard to the demo!

Figure 7.30 `DEMO7_13.EXE` in action.

### Bitmap Rotation and Scaling

DirectDraw supports both bitmap rotation and scaling, as shown in Figure 7.31. However, only the HAL supports rotation. This means that if there isn’t hardware support for rotation, you’re out of luck. You might ask, “Why does the HEL support scaling and not rotation?” The answer is that bitmap rotation is about 10–100 times slower than a scaling operation, and Microsoft found that no matter how well they wrote software rotation code, it was just too slow! So the long and the short of it is that you can always count on scaling, but not rotation. You can always write your own bitmap rotation function, but this is rather complex and not really necessary for 3D polygon games. I’m not going to cover it in this book.

Figure 7.31 Bitmap scaling and rotation.

Performing bitmap scaling is easy. All you need to do is change the size of the destination `RECT` to make it different from the source `RECT` image, and the image will be scaled. For example, let’s say that you have an image that’s 64×64, and you want to scale it to a size m× n and position it at (x,y). Here’s the code:

    // fill in the destination rect

    dest_rect.left   = x;

    dest_rect.top    = x;

    dest_rect.right  = x+m-1;

    dest_rect.bottom = y+n-1;

    // fill in the source rect

    source_rect.left    = 0;

    source_rect.top     = 0;

    source_rect.right   = 64-1;

    source_rect.bottom  = 64-1;

    // blt to destination surface

    if (FAILED(lpddsback->Blt(&dest_rect, lpdds_image,

              &source_rect,

              (DDBLT_WAIT | DDBLT_KEYSRC),

              NULL)))

        return(0);

That’s easy enough! Rotation is a little harder, though, because you have to set up a DDBLTFX structure. To perform a rotation operation on a bitmap. you must have hardware acceleration that supports it (very rare) and then set up a DDBLTFX structure, as follows:

    DDBLTFX ddbltfx; // this holds our data

    // initialize the structure

    DDRAW_INIT_STRUCT(ddbltfx);

    // set rotation angle, note that each unit is in 1/100

    // of a degree rotation

    ddbltfx.dwRotationAngle = angle; // each unit is

Then you make the call to `Blt()` as you normally would, but you add the flag `DDBLT_ROTATIONANGLE` to the flags parameter and add the `ddbltfx` parameter like this:

    // blt to destination surface

    if (FAILED(lpddsback->Blt(&dest_rect, lpdds_image,

         &source_rect,

         (DDBLT_WAIT | DDBLT_KEYSRC | DDBLT_ROTATIONANGLE),

         &ddbltfx)))

        return(0);

And if you have hardware-accelerated rotation, the bitmap will rotate!

> Note: You can determine if your hardware has rotation support by querying the surface capabilities of the `DDSCAPS` structure of a surface and looking at the `DDFXCAPS_BLTROTATION*` caps flags in the `dwFxCaps` member of `DDSCAPS`. You can query the capabilities of a surface with the `IDIRECTDRAWSURFACE4::GetCaps()` function, which I’ll cover at the end of the chapter.

Before moving on to demos of DirectDraw scaling and rotation, I want to talk a little about sampling theory and how you would go about implementing scaling, at the very least, in software.

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

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 in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.