Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

SpaceWarrior - 2D DirectDraw Game - Part I

0.00/5 (No votes)
3 Jan 2007 1  
An article on creating a simple 2D DirectDraw game (the beginning).

The Book - Screenshot

Introduction

It was some time ago that I decided to create a modern computer game, so I started coding immediately. But there was a problem. What type of a game to build? What will be the story of my game? Where to find graphics for my game? Will it be a 2D or 3D game? And finally, how do I create the game at all?

My first work was a GDI based side-scrolling game. But then, the real game developers will never use Windows GDI to program a computer game. Why? It is a not so hard thing to learn and to use. Everyone can make a simple sprite moving around on the screen using keyboard keys or a mouse. So where was the problem then?

The Windows GDI is too slow to be a game programming option. But BitBlt() works very fast, right? What do you need more to make a game?

Well, basically, you can make a game using just GDI. But GDI works with a Windows DDI (Device Driver Interface) when it must access a graphics card on your computer. Also, using MCI for sound playback adds another performance hit on your system. But, still, you may get away with a simple 2D scrolling game. What will happen if you want to build, say a strategy game, like the Age Of Empires? Or a 3D game of any kind? It just won't work with GDI. You must find another victim.

Then, I realised that I need DirectX and its components. But, I didn't know anything about it. Everyone said it is a very hard thing to learn by yourselves. Microsoft documentation, although it covers everything, is not the best way to go, I know that now.

Then, I took the search for a "computer game book" on Google. Many books came out, but one of them was different. It's name is well known to computer game developers all around the world - Tricks of the Windows Game Programming Gurus, by Andre LaMothe.

It has around 1000 pages, and covers each part of the game programming task. And there is not a single task in the list... So, here I will give you a short review of this book: what is inside, how it can be used, where to go next...

The book

Reading the book will take you directly to the first game programming question: What type of a game to create? So, you have to make a decision about the type of the first game you will create. It must be a simple game, just to learn the concepts of the game development process. OK, I said, it will be a 2D shooter game. 3D games are still out of my league, so I will not waste your time on that topic.

What will be the game story? Again, something simple, like an asteroid field you must get through, while destroying your enemies which will fight you back.

Game graphics? Well, either you'll steal someone's work, or you'll build your own. What tools to use? Some 3D modeler and painting program will be enough.

Sounds in the game? Try with some sound editing program to modify existing ones or create your own.

Now, we have all parts we need to put together and get the game, right? Almost, but we still need a glue to keep these things together, otherwise each will follow its own path to the oblivion. Here, the book starts to make a mixture which will get us out of this situation.

How does each game live, and how is each game organized? Each game has a beginning, the middle part, and the end. Two of these three things you can have done for you, since they cover DirectX components' loading and un-loading. So, that means that our main game stuff is in the middle part, right? Absolutely. So, what's inside that middle part? It's a million dollar secret that you have to find out. Let's start with a little help from the book.

What do we need to know before we start building the game? Some programming language is more than enough, and I prefer C++. We also need some basic knowledge of how the Windows system is organized: windows, controls, menus, resources etc. In our game, we will need just a single window - the main game window, some game resources mentioned above (sounds and graphics), and a game story. We will need neither standard nor custom controls, no menus, nothing more, but a good will and some extra time.

The main game window

Here, we will create the main game window, we need so much to continue. No MFC will be mentioned here, so if you don't like the Win32 SDK, then you could look for another game article that deals with that topic. By the way, you need no MFC to build a game. Let's create an empty Win32 Project in MS Visual Studio, and add a new main.cpp file with the following:

// Some usual definitions and headers


#define WIN_32_LEAN_AND_MEAN

#include "windows.h"

#include "windowsx.h"



// Declarations we use

#define WINDOW_CLASS_NAME        "MyWindow_Class"

// Macros we use

#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)


// Some global variables that we need

HWND g_hMainWnd = NULL;
HINSTANCE g_hInstance = NULL;


// Some global functions we need also

LRESULT CALLBACK WindowProc(HWND hWnd, 
        UINT msg, WPARAM wParam, LPARAM lParam);
int Game_Init(void* pParms=NULL, int numParms=0);
int Game_Main(void* pParms=NULL, int numParms=0);
int Game_Shutdown(void* pParms=NULL, int numParms=0);


// Now comes the application entry point

int WINAPI WinMain(HINSTANCE hInstance, 
    HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    // Some local variables

     WNDCLASSEX winClass;
    HWND hWnd;
    MSG msg;

    // Fill window class structure which describes the main game window

    winClass.cbSize = sizeof(WNDCLASSEX);
    winClass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    winClass.lpfnWndProc = WindowProc;
    winClass.cbClsExtra = 0;
    winClass.cbWndExtra = 0;
    winClass.hInstance = hInstance;
    winClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    winClass.lpszMenuName = NULL;
    winClass.lpszClassName = WINDOW_CLASS_NAME;
    winClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    // The main game window will be black with default Windows icon and cursor


    // Save application instance handle

    g_hInstance = hInstance;

    // Register window class

    if (!RegisterClassEx(&winClass))
    {
        return (0);
    }

    // Create the main game window

    if (!(hWnd = CreateWindowEx(NULL, WINDOW_CLASS_NAME, "Main Game Window", 
        WS_POPUP | WS_VISIBLE, 0, 0, 400, 300, NULL, NULL, hInstance, NULL)))
    {
        return (0);
    }

    // Save main game window handle

    g_hMainWnd = hWnd;

    // Initialize game here

    if (!Game_Init())
    {
        return (0);
    }

    // Enter main event loop

    while (TRUE)
    {
        // Test for a window message

        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            // Test for quit message

            if (msg.message == WM_QUIT)
                break;

            // Translate any accelerator keys

            TranslateMessage(&msg);

            // Send message to window procedure

            DispatchMessage(&msg);
        }

        // Main game processing here

        if (!Game_Main())
        {
            break;
        }
    }

    // Shutdown game here

    if (!Game_Shutdown())
    {
        return (0);
    }

    // Return to Windows

    return (msg.message);
 }

So, you see all three parts of our game here. Only Game_Main() is interesting for me and you, because the other two (Game_Init() and Game_Shutdown()) can change in the future. We will write all the game logic in this single function call. Why? Because we need no more.

Message loop

This part is easy. We have provided above the main game window message filter function called WindowProc(). Here it is:

LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
     // Check the message

    switch (msg)
    {
        case WM_DESTROY:
        {
            // Send quit message

            PostQuitMessage(0);
        }
        break;

        default:
        {
            // Default message processing

            return DefWindowProc(hWnd, msg, wParam, lParam);
        }
        break;
    }

    return (0);
}

We can process all keyboard or mouse inputs from the user in the body of this function, we can destroy the main game window, or create another, pause our game etc. All Win32 applications are exactly the same till this part. Now comes the game stuff.

Game parts

We have declared the three game functions above: Game_Init(), Game_Main(), and Game_Shutdown(). Here they are:

int Game_Init(void* pParms, int numParms)
{
     // We will init the DirectX sub-system here


    return (1);
}

int Game_Main(void* pParms, int numParms)
{
     // We will write our game logic here


    // Test for ESC key pressed

    if (KEYDOWN(VK_ESCAPE))
    {
        // Destroy main game window

        PostMessage(g_hMainWnd, WM_CLOSE, 0, 0);
    }

    return (1);
}

int Game_Shutdown(void* pParms, int numParms)
{
     // We will shutdown the DirectX sub-system here


    return (1);
}

This is all that you need to create the main game window. You just need the game elements now...

Conclusion

You can build the example provided in this article and run it. You should see a black window 400x300 pixels large, which you can destroy by pressing the ESC key on your keyboard.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here