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

#### Creating Offscreen Surfaces

Creating an offscreen surface is almost identical to creating the primary buffer except for the following:

  1. You must set the `DDSURFACEDESC2.dwFlags` to `(DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT)`.
  2. You must set dimensions of the requested surface in `DDSURFACEDESC2.dwWidth` and `DDSURFACEDESC2.dwHeight`.
  3. You must set the `DDSURFACEDESC2.ddsCaps.dwCaps` to `DDSCAPS_OFFSCREENPLAIN | memory_flags`, where `memory_flags` determines where you want the surface to be created. If you set it to `DDSCAPS_VIDEOMEMORY`, the surface will be created in VRAM (if there’s any space). If you set `memory_flags` equal to `DDSCAPS_SYSTEMMEMORY`, the surface will be created in system memory, and so the blitter will be almost unused because the bitmap data will have to be transferred over the system bus.

As an example, here’s a function that creates any type of surface you request:

    LPDIRECTDRAWSURFACE4 DDraw_Create_Surface(int width, int height,

                                              int mem_flags)

    {

    // this function creates an offscreen plain surface

    DDSURFACEDESC2 ddsd;         // working description

    LPDIRECTDRAWSURFACE4 lpdds;  // temporary surface

    // initialize structure

    DDRAW_INIT_STRUCT(ddsd);

    // set to access caps, width, and height

    ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;

    // set dimensions of the new bitmap surface

    ddsd.dwWidth  =  width;

    ddsd.dwHeight =  height;

    // set surface to offscreen plain

    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | mem_flags;

    // create the surface

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

       return(NULL);

    // set color key to color 0

    DDCOLORKEY color_key; // used to set color key

    color_key.dwColorSpaceLowValue  = 0;

    color_key.dwColorSpaceHighValue = 0;

    // now set the color key for source blitting

    lpdds->SetColorKey(DDCKEY_SRCBLT, &color_key);

    // return surface

    return(lpdds);

    } // end DDraw_Create_Surface

For example, if you wanted to create a 64×64 pixel surface in VRAM, you’d make the following call:

    LPDIRECTDRAWSURFACE4 space_ship = NULL; // used to hold surface

    // create surface

    if (!(space_ship = DDraw_Create_Surface(64,64,DDSCAPS_VIDEOMEMORY)))

        { /* error */ }

When you’re creating surfaces to hold bitmaps, only create VRAM surfaces of bitmaps that you’re going to draw a lot. Moreover, create them in order from largest to smallest.

Now you can do whatever you want with the surface. For example, you might want to lock it so you can copy a bitmap to it. Here’s how you would do that:

    DDSURFACEDESC2 ddsd; // directdraw surface description

    // initialize the structure

    DDRAW_INIT_STRUCT();

    // lock the surface, check for error in RL (real-life)

    space_ship->Lock(NULL, &ddsd,

                     DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,

                     NULL););

    // do what you will to ddsd.lpSurface and ddsd.lPitch

    // unlock

    space_ship->Unlock(NULL);

Then when you’re done with the surface (the game is over, whatever) you must release the surface back to DirectDraw as usual with `Release()`:

    if (space_ship)

        space_ship->Release();

That’s all there is to creating an offscreen surface with DirectDraw! Now let me show you how to blit it to another surface, such as the back buffer or primary surface.

#### Blitting Offscreen Surfaces

Now that you know how to load bitmaps, create surfaces, and use the blitter, it’s time to put it all together and do some real animation! The goal of this section is to load bitmaps that contain the frames of animation for some object (ship, creature, whatever), create a number of small surfaces to hold each frame of animation, and then load the images into each of the surfaces. Once all the surfaces are loaded with bitmap data, you want to blit the surfaces on the screen and animate the object!

Actually, you already know how to accomplish all these steps. About the only thing you haven’t done is use the blitter to blit from a surface other than the back buffer to the primary buffer, but there’s no difference. Referring to Figure 7.27, you see a number of small surfaces, each with a different frame of animation. In addition, you see both a primary surface and a back buffer surface. The plan is to load all the bitmaps into the small surfaces (the object to animate), use the blitter to blit the small surfaces onto the back buffer, and page flip to see the results. Every so often, you’ll blit a different image and move the destination of the blit slightly to animate and move the object.

Figure 7.27 Blitting offscreen surfaces to the back buffer.

#### Setting Up the Blitter

To set up the blitter, you need to do the following:

  1. Set up the source `RECT` to blit from. This will be the small surface (8×8, 16×16, 64×64, etc.) containing the image of interest. Usually the coordinates will be (0,0) to (width–1, height–1)—that is, the whole surface.
  2. Set up the destination `RECT`, which will usually be the back buffer. This part is a little tricky because you want to copy the source image at some location (x,y), so the `RECT` should be set with this in mind: (x,y) to (x+width-1,y+height-1).
  3. Make a call to `IDIRECTDRAWSURFACE4::Blt()` with the proper parameters—which you’ll see shortly.

> Note: If you make the destination `RECT` larger or smaller than the source `RECT` (the image), the blitter will scale the image appropriately to fit—this is the basis of 2.5D sprite-scaled games.

There’s one problem that I must address before you see the call to the `Blt()` function—color keying.

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.