Hey and welcome to the wonderful world of DirectX Game Programming. This is the first of a couple of tutorials that will aim to teach the basics of DirectX so that even novice C/C++ programmers can create games! In part 1 of this series, I will show you how to set up a window that is suitable for DirectX games and then how to initialize DirectX itself, this may sound a bit boring but it is necessary before we can jump into better stuff! The saying: "One must learn to walk before they run" is especially true in DirectX or you will just write read-only code and will not know what is going on! DirectX works only on windows so I am sorry for the Mac and Linux users but you can try take a look at OpenGL as an alternative.

So enough for introductions, lets dive in:

Win32 Primer:
If you have never done any Windows programming before than do not worry as You only need a basic windows application setup before you have an environment that is suitable for DirectX API/Lib to take over.

I am sure you are getting bored now, so let's dive into our windows program and then I will dissect it and show you how it all works:

Ok, now just compile that in your IDE (I am using Visual Studio 2010 Express) and you will have a windows application with some text in the middle of the top part of the screen that says: "Hello Windows".

Like so:

Windows Messaging

Before we start dissecting our first Windows program, You must have a basic understanding of the messaging system.

Windows Programs are event-driven. In other-wards Windows uses system-wide messages to communicate, i.e.: Messages that are seen by the entire system.

Windows messages are small packets of data sent by the operating system to running programs that tells the program that an event has occurred. An event is for example, a key press or that the program's window has been redrawn etc...

A Handle is essentially a reference for the operating system. It allows the system resources to know what you are referring to when it is passed in an API call. A window handle is normally wrapped in an instance of a class such as HWND which in this case is a handle to a Win32 window.

Program code is stored in a single memory space in Windows (note variables and program data are stored individual spaces). A instance refers to this space so that the Windows system can run our program.

Message Type simply refers to whether or not the message is system defined or application defined. See this for more on the topic.

Each windows program is handed any event that occurs and dependent on the program code, will either handle the event or give it back to the message stream.

Why is a windows messaging system necessary? Well a easy way to think about it is to think of it as the nervous system within one's body. Without a nervous system, our brain would not be able to perceive what is happening to us, we would not feel pain for example as there would be no way for our brain to receive the message that the nervous system would send as there are no pathways. The Windows Messaging system is similar, events for example an input event such as a key press from the keyboard is relayed via the message stream to the our program via the OS. If we need the message then we deal with it if not we ignore it.

Dissecting the program

The most important part of our windows program is the function WinMain. It is the initial entry point of our application and the OS calls this function when starting the window. The job of WinMain is to set up the program, and then to set up the main message loop for the program.

The first parameter - HINSTANCE hInstance - identifies the instance of the program being called.

The second parameter - HINSTANCE hPrevInstance - identifies the previous instance of the program, if hPrevInstance is NULL then this is the first instance of the program. It is generally routine to check if the hInstance is the same as hPrevInstance as you do not want the same two instances running at once and if that is the case, then you normally kill hPrevInstance.

The third parameter is a string that contains the command-line parameters passed to the program (if any).

The fourth parameter specifies how the program window is to be displayed.

There is a essential part in WinMain which is where we set the window's properties namely by creating a WNDCLASS object wc and registering our form with windows. This details of the properties are listed in the comments, but take another look:

//set the new window's properties
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW; //this is necessary to ensure that the window is redrawn if the width or height of the window is changed
wc.lpfnWndProc = (WNDPROC) WinProc; //Here we set our message handler namely to our WinProc function, without this our window cannot handle messages as it has no means to do so
wc.cbClsExtra = 0; //add extra bytes of memory to a windows procedure, not needed in this case
wc.cbWndExtra = 0; //add extra bytes of memory to a windows procedure, not needed in this case
wc.hInstance = hInstance; //set the instance of our window
wc.hIcon = NULL; //set the window icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); //set the window's cursor
wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); //set the background colour (white in this case)
wc.lpszMenuName = NULL; //set's the menu, we do not use a menu as of now
wc.lpszClassName = WINDOWTITLE.c_str(); //sets the class name, this is essential as it gives the window a specific class name and is used for message handling along with hWnd
wc.hIconSm = NULL;
RegisterClassEx(&wc); //register the window with Windows

We used a switch statement to handle the various messages that we want to. (You could use if statements but I find this easier). Here we have handled two messages WM_PAINT and WM_DESTROY .

WM_PAINT refers to actually drawing in our window. We first get the dimensions of the screen and store them in a RECT variable as this is necessary for our DrawText() function. We then use a PAINTSTRUCT variable which is used to start and stop a screen update. We then create a variable hdc that receives the device context that we are going to draw onto. We then use the DrawText function to draw some text to the screen and once we are done, we then use the EndPaint() function and pass our window handle and the PAINTSTRUCT, this unlocks the device again. The device is "locked" so to speak during the period when we are drawing text so that the screen does not refresh and we might get interrupted whilst painting, do not be too worried about this. It is just an aesthetic feature to make our first window program more interesting.

The WM_DESTROY message tells the window that is it time to exit. We simply close the game loop and PostQuitMessage(0); which essentially tells Windows that our program exited successfully and no errors occurred.

If there are messages that we have not used, we throw them back to the message stream with: return DefWindowProc(hWnd, message, wParam, lParam);

Whew! We are going at a fast pace as this stuff is rather easy? You may not understand it all now but you will hopefully understand it as you use it in the next couple of tutorials.

WinProc and WinMain work together to handle application events such as responding to key input.

Here is a nice way to think about how these two functions work together:

The two parameters are easy enough:
The first parameter - HINSTANCE hInstance - is passed by WinMain with the program instance that it receives from windows (i.e. the instance that is running).

The second parameter - int nCmdShow - is passed by WinMain which WinMain receives from Windows. It contains extra properties such as SW_HIDE (hide the window), but we do not use it for now.

The rest of the application is fairly simple enough. We create a handle to the window that we are going to create and then we set basic properties such as dimension of the window, title bar etc... We then check if there was any errors whilst creating the window handle if so we return 0 (or false) otherwise we display the window using the ShowWindow and UpdateWindow functions. If all went well, we update WinMain that the Window was created successfully by returning 1 (or true).

createInstance in essence creates our user interface.

Making it all work together
Finally we must make all our functions work together to run our program effectively, the onus is placed on WinMain, take another look at the function:

/*
* Entry point for a windows program
*/
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//set the new window's properties
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW; //this is necessary to ensure that the window is redrawn if the width or height of the window is changed
wc.lpfnWndProc = (WNDPROC) WinProc; //Here we set our message handler namely to our WinProc function, without this our window cannot handle messages as it has no means to do so
wc.cbClsExtra = 0; //add extra bytes of memory to a windows procedure, not needed in this case
wc.cbWndExtra = 0; //add extra bytes of memory to a windows procedure, not needed in this case
wc.hInstance = hInstance; //set the instance of our window
wc.hIcon = NULL; //set the window icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); //set the window's cursor
wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); //set the background colour (white in this case)
wc.lpszMenuName = NULL; //set's the menu, we do not use a menu as of now
wc.lpszClassName = WINDOWTITLE.c_str(); //sets the class name, this is essential as it gives the window a specific class name and is used for message handling along with hWnd
wc.hIconSm = NULL;
RegisterClassEx(&wc); //register the window with Windows
if (!createInstance(hInstance,nCmdShow)) return 0; //createInstance is a helper function that basically creates the program window
// ^ test if something went wrong creating the window, if so then exit
//main message loop
MSG msg;
while (GetMessage(&msg, NULL,0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}

The logic is pretty simple, we first set up the window's properties and then we create the window by calling createInstance. If something went wrong, we return a value of 0 to indicate that program execution failed otherwise we get into our message loop. This message loop is event-driven in otherwards it will keep running whilst events are occuring then it will handle the messages appropriately. note that the MSG variable contains the actual data concerning the messages.

NOTE: You may get a error when using c_str(), the workaround is to make sure your project is using multi-byte settings and not unicode, in VS2010, You would simply go:
Project -> Properties -> Configuration Properties: General -> Charachter Set and select use multi-byte charachter set.

That's it for our basic Win32 Primer and I hope it has helped!

Initializing DirectX:
Now that we have the basics of windows out of the way, we can begin looking at how to setup the DirectX SDK.

DirectX is basically just an API (Application Programming Interface) that provides an interface to the low-level hardware and provides us with the tools necessary so that we can develop games without the use of the API or GDI. DirectX is much faster than the latter solution too!

DirectX is closely integrated with Windows and will not work on any other O/S as it relies on the basic libraries in the Windows API to run.

Let's go over some of the DirectX components that we will end up using:

Direct3D -This is the rendering component that provides access to the video card and renders our 2D or 3D Graphics!

DirectSound - This is the older audio component that was used to play audio, we will use XACT.

XACT - This is the new audio system that DirectX provides, it is also used in the XNA Game Studio SDK.

DirectInput - This is the component of DirectX that handles recieving input from peripheral devices such as the keyboard, mouse etc...

Now that you have a basic overview, You must first actually install DirectX. The SDK can be downloaded from here.
Simply install it like a normal application once downloaded.

Okay we will now get to creating a program that initializes DirectX and creates a Direct3D Device. A Direct3D Device gives you access to the video card's primary surface.

In order to actually use Direct3D or DirectX. You must include the relevant headers, in this case. You must include: d3d9.h like so: #include <d3d9.h>

In order to access these headers, you must include the relevant libraries, either via the use of the pragma preprocessor directive or by actually configuring your IDE. If you are using Visual Studio 2010 Express then this tutorial is essential (or just google how to as there are numerous tutorials on how to do this) to learning how to configure the DirectX SDK so that you can use it.

Direct3D Interfaces:

In order to use Direct3D, you must have at minimum two variables, one for the Direct3D interface itself and one for the graphics device that you are using. In DirectX9, the direct3D interface is declared like so:

LPDIRECT3D9 d3d = NULL;

whilst the graphics device (or object) is declared like so:

LPDIRECT3DDEVICE9 d3ddev = NULL;

The LPDIRECT3D9 object is the object that controls all rendering whilst the LPDIRECT3DDEVICE9 simply gives us access to the graphics card. The prefix LP indicates that this is a Long Pointer which operate exactly the same as regular pointer on 32 bit machines. For more, you can try take a look at this.

(Excuse me for all the links in this tutorial but I would have to write practically an entire book if I tried to explain every miniscule detail.)

We first off make sure that our Direct3D device is initialized correctly.
We then call a function called clear and what this literally does is clear the back buffer to a colour. In this case, we clear it to red but you could clear it to any colour really (black - 0,0,0 is common). The purpose of this is so that upon new frame is drawn, the backbuffer is cleared completely so that we do not end up with graphical artifacts or stuff that we did not mean to redraw.

We then begin rendering by rendering BeginScene() and then we stop rendering with EndScene(). At the moment we are not rendering any bitmaps etc but this is necessary in order to actually render to the graphics device' back buffer. We finally call a function called Present() and this copies our back buffer to the front buffer which is then displayed on the screen.

We simply use a MessageBox to display to the user that our program is going to end and then we free the memory so that our Direct3D interfaces do not point to nothing. The Game_End function is called when a WM_DESTROY message occurs and this occurs by default when the user clicks the "X" button on the top of the frame.

Double-Buffering
You probably heard me babble on about backbuffer and front buffer's here and there, well this is a method that we use called double-buffering which is used to display smooth graphics. A simple explanation of this concept is the following:

We draw whatever we need to draw to a back buffer and then when we have drawn what we needed to, to the back buffer we can copy it straight to the front buffer of our graphics device and thus it will be displayed on the screen as one complete image. If we used a single buffer and only drew to that then the problem is that as we drew more, the user would see the actual objects being drawn which would result in flickering etc...

Here is a image so that you get what I mean:

Time to run it for yourself!

Ok hopefully you have had the patience to wade through all this text but for now let's actually create your first DirectX 9.0c program! Here is the code:

And that's it for the basics on Windows Programming and how to Initialize DirectX. I may have omitted a couple of things to keep this tutorial shorter but I will explain them in the next few tutorials if necessary. I hope this tutorial has helped you! I will publish a couple more on the basics and in the end maybe publish a tutorial on how to make a simple game with DirectX. Thanks for your time.