IntroductionWelcome to my DirectX tutorials. This is the first in a number of tutorials that should at least help you on the way to make Windows games using Microsoft DirectX 8. I have decided to write these tutorials for two reasons. Firstly, I’m a complete beginner when it comes to DirectX. So, the idea is that as I learn, I can write a short tutorial that should reinforce my knowledge. Secondly, the SDK isn’t the most helpful thing in the world for complete beginners starting out in game development. Also, there isn’t a great deal of stuff out there on the Internet for beginners and DirectX 8, so this should help. One other thing, as I said, I am a beginner. So, if you spot something that is incorrect in these tutorials then please let me know by emailing me at: webmaster@andypike.com. You can download the full source code and tutorial text by clicking the "Download Source" and "Download Tutorial" links above. COMWhat is COM? Well, the Component Object Model is basically a library of methods. You can create COM objects in your program and then call the methods that they expose to you. Methods are grouped together in collections of related methods. These collections are known as Interfaces. You could think of a COM object as a library of functions arranged by subject. DirectX provides a whole host of these libraries that will enable you to create 3D games. The best part is, that DirectX takes care of a lot of the hard stuff for you, so it is pretty easy to get something simple up and running.

There is a lot more to COM than that, for a full description take a look in the SDK. All you really need to worry about is that you release all of your COM objects/interfaces before your program terminates. You should make sure that you release them in the reverse order to that which you created them. For example:

1. Create interface A.
2. Create interface B.
3. Release interface B.
4. Release interface A.

You release the COM object by calling their Release method.

Page FlippingWhat is Page Flipping? Well, think of a flipbook. This is a number of pages with a slightly different drawing on each page. Then, when you hold the corner and “flip” the pages, it looks like the picture is moving. This is how DirectX Graphics works. You draw all of your objects onto a hidden page, known as the “Back Buffer”. Then when you have finished, flip it to the Front Buffer and repeat the process. As the user is looking at the new front buffer, your program will be drawing onto the back buffer.

What would happen without Page Flipping? Without Page Flipping, the user would see each object appear as it was drawn, which isn’t what you want at all.

So, your game will basically consist of a loop, known as the “Game Loop”. Each time around the loop you process your game logic so you know where your objects will be. Next, you clear the Back Buffer. Then draw the current scene onto it. When this is done, flip it to the front and start the loop again. This will continue until the game is shut down. You may have a number of Back Buffers, this is known as a “Swap Chain”. DevicesWhat is a device? Basically, a device (as far as DirectX Graphics is concerned) is your machines 3D card. You can create an interface that represents your device and then use it to draw objects onto the back buffer. Game LoopWhat is the game loop? Well, the game loop is a code loop that loops until the program is shut down. Inside the game loop is where it all happens: objects are drawn (rendered), game logic is processed (AI, moving objects and scoring etc) and Windows messages are processed. Then it's all done again until the program is closed down. Creating Your First ProjectOkay, that’s enough theory lets get started. Follow the step-by-step guide below to create your first DirectX Graphics project.

1. In Visual C++ create a new Win32 Application.
a. File > New
b. From the Projects tab select Win32 Application
c. Enter a name for your project such as “DX Project 1”
d. Select a folder for the location of your source code files
e. Click Next
f. Select the empty project option.
g. Click Finish
2. Make sure that your project settings are correct.
a. Project > Settings...
b. On the Link tab, make sure that "d3d8.lib" is in the list of Object/Library Modules. If it isn’t simply type it in.
3. Make sure that your search paths are correct.
a. Tools > Options > Directories Tab
b. In the "Show directories for" drop-down, select "include files".
c. If it does not exist already, add the following path: <SDK INSTALL PATH>\include.
d. Make sure that this path is at the top of the list by clicking on the up arrow button (if needed).
e. In the "Show directories for" drop-down, select "library files".
f. If it does not exist already, add the following path: <SDK INSTALL PATH>\lib.
g. Make sure that this path is at the top of the list by clicking on the up arrow button (if needed).
4. Add the source code.
a. File > New
b. From the Files tab, select C++ Source File
c. Enter a filename such as “Main.cpp”
d. Copy the code segment below, and then paste it into your new file.
5. Build and Run the program.
a. Press F7 to build your project
b. Press F5 to run
#include <d3d8.h>

LPDIRECT3D8 g_pD3D = NULL;
LPDIRECT3DDEVICE8 g_pD3DDevice = NULL;

HRESULT InitialiseD3D(HWND hWnd)
{
//First of all, create the main D3D object. If it is created successfully we
//should get a pointer to an IDirect3D8 interface.
g_pD3D = Direct3DCreate8(D3D_SDK_VERSION);
if(g_pD3D == NULL)
{
return E_FAIL;
}

//Get the current display mode
D3DDISPLAYMODE d3ddm;
if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
{
return E_FAIL;
}

//Create a structure to hold the settings for our device
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));

//Fill the structure.
//We want our program to be windowed, and set the back buffer to a format
//that matches our current display mode
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
d3dpp.BackBufferFormat = d3ddm.Format;

//Create a Direct3D device.
if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDevice)))
{
return E_FAIL;
}

return S_OK;
}

void Render()
{
if(g_pD3DDevice == NULL)
{
return;
}

//Clear the backbuffer to a green color
g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0);

//Begin the scene
g_pD3DDevice->BeginScene();

//Rendering of our game objects will go here

//End the scene
g_pD3DDevice->EndScene();

//Filp the back and front buffers so that whatever has been rendered on the back buffer
//will now be visible on screen (front buffer).
g_pD3DDevice->Present(NULL, NULL, NULL, NULL);
}

void CleanUp()
{
if(g_pD3DDevice != NULL)
{
g_pD3DDevice->Release();
g_pD3DDevice = NULL;
}

if(g_pD3D != NULL)
{
g_pD3D->Release();
g_pD3D = NULL;
}
}

void GameLoop()
{
//Enter the game loop
MSG msg;
BOOL fMessage;

PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);

while(msg.message != WM_QUIT)
{
fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);

if(fMessage)
{
//Process message
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//No message to process, so render the current scene
Render();
}

}
}

//The windows message handler
LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
case WM_KEYUP:
switch (wParam)
{
case VK_ESCAPE:
//User has pressed the escape key, so quit
DestroyWindow(hWnd);
return 0;
break;
}
break;

}

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

//Application entry point
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT)
{
//Register the window class
WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WinProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"DX Project 1", NULL};
RegisterClassEx(&wc);

//Create the application's window
HWND hWnd = CreateWindow("DX Project 1", "www.andypike.com: Tutorial 1",
WS_OVERLAPPEDWINDOW, 50, 50, 500, 500,
GetDesktopWindow(), NULL, wc.hInstance, NULL);

//Initialize Direct3D
if(SUCCEEDED(InitialiseD3D(hWnd)))
{
//Show our window
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);

//Start game running: Enter the game loop
GameLoop();
}

CleanUp();

UnregisterClass("DX Project 1", wc.hInstance);

return 0;
}