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

And I’ve found that adding a little logic like this helps if the function errors out for some stupid reason:

    while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT));

> Warning: Both the back buffer surface and the primary surface must be unlocked to perform the flip, so make sure you’ve unlocked them both before trying a call to `Flip()`.

For an example of page flipping, check out `DEMO7_5.CPP|EXE`. I took `DEMO7_4.CPP` and changed the double buffering to page flipping, and of course I updated the `Game_Init()` code to create a complex surface with a single back buffer. Here are `Game_Init()` and `Game_Main()` for your review:

    int Game_Init(void *parms = NULL, int num_parms = 0)

    {

    // this is called once after the initial window is created and

    // before the main event loop is entered, do all your initialization

    // here

    LPDIRECTDRAW lpdd_temp;

    // first create base IDirectDraw interface

    if (FAILED(DirectDrawCreate(NULL, &lpdd_temp, NULL)))

       return(0);

    // now query for IDirectDraw4

    if (FAILED(lpdd_temp->QueryInterface(IID_IDirectDraw4,

                                        (LPVOID *)&lpdd4)))

       return(0);

    // set cooperation to full screen

    if (FAILED(lpdd4->SetCooperativeLevel(main_window_handle,

                   DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX |

                   DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))

       return(0);

    // set display mode to 640×480×8

    if (FAILED(lpdd4->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT,

                                     SCREEN_BPP,0,0)))

       return(0);

    // clear ddsd and set size

    DDRAW_INIT_STRUCT(ddsd);

    // enable valid fields

    ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

    // set the backbuffer count field to 1, use 2 for triple buffering

    ddsd.dwBackBufferCount = 1;

    // request a complex, flippable

    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |

                          DDSCAPS_COMPLEX | DDSCAPS_FLIP;

    // create the primary surface

    if (FAILED(lpdd4->CreateSurface(&ddsd, &lpddsprimary, NULL)))

       return(0);

    // now query for attached surface from the primary surface

    // this line is needed by the call

    ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

    // get the attached back buffer surface

    if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)));

    // build up the palette data array

    for (int color=1; color < 255; color++)

        {

        // fill with random RGB values

        palette[color].peRed   = rand()%256;

        palette[color].peGreen = rand()%256;

        palette[color].peBlue  = rand()%256;

        // set flags field to PC_NOCOLLAPSE

        palette[color].peFlags = PC_NOCOLLAPSE;

        } // end for color

    // now fill in entry 0 and 255 with black and white

    palette[0].peRed     = 0;

    palette[0].peGreen   = 0;

    palette[0].peBlue    = 0;

    palette[0].peFlags   = PC_NOCOLLAPSE;

    palette[255].peRed   = 255;

    palette[255].peGreen = 255;

    palette[255].peBlue  = 255;

    palette[255].peFlags = PC_NOCOLLAPSE;

    // create the palette object

    if (FAILED(lpdd4->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 |

                                    DDPCAPS_INITIALIZE,

                                    palette,&lpddpal, NULL)))

    return(0);

    // finally attach the palette to the primary surface

    if (FAILED(lpddsprimary->SetPalette(lpddpal)))

       return(0);

    // return success or failure or your own return code here

    return(1);

    } // end Game_Init

    /////////////////////////////////////////////////////////

    ////

    int Game_Main(void *parms = NULL, int num_parms = 0)

    {

    // this is the main loop of the game, do all your processing

    // here

    // make sure this isn’t executed again

    if (window_closed)

       return(0);

    // for now test if user is hitting ESC and send WM_CLOSE

    if (KEYDOWN(VK_ESCAPE))

       {

       PostMessage(main_window_handle,WM_CLOSE,0,0);

       window_closed = 1;

       } // end if

    // lock the back buffer

    DDRAW_INIT_STRUCT(ddsd);

    lpddsback->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);

    // alias pointer to back buffer surface

    UCHAR *back_buffer = (UCHAR *)ddsd.lpSurface;

    // now clear the back buffer out

    // linear memory?

    if (ddsd.lPitch == SCREEN_WIDTH)

        memset(back_buffer,0,SCREEN_WIDTH*SCREEN_HEIGHT);

    else

       {

       // non-linear memory

       // make copy of video pointer

       UCHAR *dest_ptr = back_buffer;

       // clear out memory one line at a time

       for (int y=0; y<SCREEN_HEIGHT; y++)

           {

           // clear next line

           memset(dest_ptr,0,SCREEN_WIDTH);

           // advance pointer to next line

           dest_ptr+=ddsd.lPitch;

           } // end for y

       } // end else

    // you would perform game logic...

    // draw the next frame into the back buffer, notice that we

    // must use the lpitch since it's a surface and may not be linear

    // plot 5000 random pixels

    for (int index=0; index < 5000; index++)

        {

        int   x   = rand()%SCREEN_WIDTH;

        int   y   = rand()%SCREEN_HEIGHT;

        UCHAR col = rand()%256;

        back_buffer[x+y*ddsd.lPitch] = col;

        } // end for index

    // unlock the back buffer

    if (FAILED(lpddsback->Unlock(NULL)))

       return(0);

    // perform the flip

    while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT)));

    // wait a sec

    Sleep(500);

    // return success or failure or your own return code here

    return(1);

    } // end Game_Main

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.