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
73 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
 The Design
 Map Files
 Data Structures
 Writing the Code
 Drawing the Map

 Get the source
 Printable version
 Discuss this article
 in the forums



The Series
 Beginning Windows
 Programming

 Using Resources
 in Win32 Programs

 Tracking Your
 Window/Using GDI

 Introduction
 to DirectX

 Palettes and Pixels
 in DirectDraw

 Bitmapped Graphics
 in DirectDraw

 Developing the
 Game Structure

 Basic Tile Engines
 Adding Characters
 Tips and Tricks

Writing the Code

First things first: let's see what this is going to look like. The structure of this demo will be very similar to the other Windows programs we've written so far in this series, only it will be a lot more exciting, because you'll be able to interact with it and expand upon it later. Take a look:

  • Create a window.
  • Initialize DirectX:
    • Set up DirectDraw.
    • Create three surfaces: primary, back buffer, and tileset.
    • Create a clipper and attach it to the back buffer.
  • Load tileset and map.
  • Main loop:
    • Handle the Windows message queue.
    • Exit loop if WM_QUIT message found.
    • Check for user input.
    • Render the map to the back buffer:
      • Find the horizontal and vertical ranges of tiles that need to be drawn.
      • Update tile pointers to account for animations.
      • Blit the first layer without color keying, so it overwrites the previous frame completely.
      • Blit the second layer with color keying.
    • Flip the frame to the primary surface.
    • Lock to a constant frame rate.
  • Shut down DirectX.
  • Return to Windows.

It's a long list of tasks compared to some of the things we've done in the past, but you already know how to do most of this. You can do all the initialization and shutdown functions, and you can handle the message queue and the user input. When the user is pressing the arrow keys -- which you can check for using the GetAsyncKeyState() function -- you simply update the camera coordinates accordingly, and the part of the code that draws the map will handle the rest. The only thing that remains to be demystified is that map-rendering process, so that's what we'll do next.

One last thing before we get into the actual map drawing. Notice that I said we will "flip" the frame to the primary surface, instead of blitting it. That means that we'll be using a technique called page-flipping, instead of the double buffering we used in article #6. It's my fault for forgetting to cover it -- sorry! Anyway, it's not hard. All you need to do is create your primary surface using DDSCAPS_FLIP and DDSCAPS_COMPLEX, with one back buffer attached. Remember, we saw an example of doing this near the end of article #4. At least, I think it was #4. :) Anyway, once you've got a back buffer chained to the primary surface, you simply copy the latter to the former by calling IDirectDrawSurface7::Flip(), which looks like this:

HRESULT Flip(
  LPDIRECTDRAWSURFACE3 lpDDSurfaceTargetOverride, 
  DWORD dwFlags
);

The first parameter is the surface in the flipping chain to flip the image to. If you pass NULL, the image cycles through the buffers in the order in which they are attached to one another, which is what we want. The second parameter should just be set to DDFLIP_WAIT, to specify that the call should not return until the flip is complete. The nice thing about page flipping is that the image isn't really getting copied! What happens is that DirectDraw switches the pointers to the two surfaces in memory, so that in essence, the back buffer becomes the primary surface, and vice versa. Nice and fast, nice and easy. Anyway, an example of all this is in the code, so let's move on.




Next : Drawing the Map