Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
89 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

  Contents

 Introduction
 The Design
 CreateSurfaces()
 DestroySurfaces()
 The Game Loop
 Switching Modes
 While Running


 Get the demo!
 Printable version

 


  The Series

 Part 1
 Part 2

 

CreateSurfaces(…)

We'll split this function up into two sections, which initialize DirectDraw for either exclusive mode or windowed mode. That is done like this:

if( bExclusive ) { // exclusive code // save the mode g_bExclusive = bExclusive; } else { // windowed code // save the mode g_bExclusive = bExclusive; }

Another thing you'll want to do is to create a global variable (g_bExclusive) to remember whether we're in exclusive mode or not; we'll use that flag during the game loop. Don't forget about the g_bExclusive flag! It's very important that we keep track of the mode.

You can place all of the code you've already written in the exclusive code section. Have it use the nWidth, nHeight, and nBPP for the display mode, etc. We'll add our own code to the windowed code section. (I'll do this with several functions, splitting them up into two sections. Just so you know what I'm doing!)

As I mentioned before, when this function is called, DirectDraw has already been created. So, the next step in initializing DirectDraw is to set the cooperative level via lpDD->SetCooperativeLevel(). Pass the handle of your main window, and DDSCL_NORMAL:

lpDD->SetCooperativeLevel(hMainWnd, DDSCL_NORMAL);

You can also OR the DDSCL_MULTITHREADED flag if you want to use multiple threads. Remember, you can't set the display mode in windowed mode; so, the next step is to create the primary surface and back buffer.

You need a very different "buffering system" in windowed mode. You can't create a primary surface with attached back buffers and flip() them, because you don't have exclusive access to the video hardware. Flipping is the process of swapping the address of the current primary surface with one of its attached back buffers. Obviously, you can't do this in windowed mode, because you're sharing the primary surface with all the other apps.

The system you need in windowed mode is to create your primary surface with this DDSURFACEDESC2:

DDSURFACEDESC2 ddsd; ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

That code simply uses the existing format of the screen for the primary surface, which, by the way, you can't change in windowed mode. Also, note that we didn't use the DDSD_BACKBUFFERCOUNT flag; that's only for exclusive mode apps.

Then you create your back buffer like so:

DDSURFACEDESC2 ddsd; ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.dwWidth = 640; // whatever you want ddsd.dwHeight = 480; // whatever you want

Note here that we didn't use the DDSCAPS_BACKBUFFER flag, because that's also just for exclusive mode apps.

Remember, in DirectDraw, the primary surface is always the entire screen. To keep yourself from drawing all over the screen in windowed mode, you attach a clipper to your primary surface, and attach it to your main window as well (that's the easy way):

LPDIRECTDRAWCLIPPER lpddClipper; lpDD->CreateClipper(...lpddClipper...); lpddClipper->SetHWnd(...hMainWnd...); lpddsPrimary->SetClipper(...lpddClipper...);

There are other parameters to these functions; for simplicity's sake I simply did not list them.

Well, that's it for the CreateSurfaces function. We'll look at cleaning up next.


Next : DestroySurfaces()