Home
Game Downloads
Backgrnd
Game Design
About

Page1, Page 2, Page 3, Page 4, Page 5, Page 6, Page 7

Game Programming Tutorial

  Note that these tutorials are a bit dated now but still apply in principle. As of now (2014), some people still want to use DirectX9 or XNA (like me) - which will mean your project will be available on all versions of Windows after XP. If you later upgrade the project to DX11 or SharpDX for example, you could develop for XBox One. Also an XNA version can easily be ported to Monogame(basically the same thing) which will make it possible to release your project on many other platforms. Since I made this tutorial, I've made an improved version which uses XNA with cleaner coding and better class arrangement. Hopefully when I have time, I can upgrade these and add information about using gpu shaders/effects.

  This tutorial will guide you step by step through the process of programming a parallax 2D side-scrolling game/editor with some elements of 3D. I will also show you tricks for creating nice artwork and music to go with it -- I warn you that this tutorial is going to get into some fairly advanced game programming stuff - so you made need to look up some of the math and programming concepts elsewhere to suppliment your understanding of what I'm talking about. Don't be discouraged though - it will start off boring and confusing but will get better later...

  It is commonly believed that one of the best tools for game programming is Visual Studio using C/C++ and I will be using DirectX to interface with the graphics accelerator. (I will also be using photoshop for the artwork) [I'll get into other languages, interfaces and tools later]

(You should download and install the directX SDK -- you can google for tutorials which will show you how to do this and get you started. Then go Tools>>Options>ProjectsAndSolutions>>VC++Directories, click "Show Directories for Executable Files" then Ctrl+Insert, click ... and browse to the [whatever your SDK directory is]Bin/x86 and do the same sort of thing under include files(look for include directory) and library files (look for Lib\x86 directory). I'll probably get into 64bit builds later -- we'll do a 32bit one for now...)
It is also improtant to make sure you add each of the librarys to your project as you need them. First make sure you've done the dollowing:
Build>>Configuration Manager -- select "Debug" and "Win32" -- we'll change it to "Release" when we're done making the game. Now go to Project Properties -- (active(debug) and active(win32)) select Configuration Properties>>General and change it to "Use Multi-Byte character set" because of the way I use strings in the coding -- otherwise you may get some compile errors -- also go into: Configuration Properties>>Linker>>Input>>Additional Dependencies -- click on additional dependencies and click the [...] button and add the following list: (you can use debug versions of the libs too but remember to change them back for release version)
d3dxof.lib
dxguid.lib
d3dx9.lib
d3d9.lib
Dxerr.lib
winmm.lib
dinput8.lib
dsound.lib
Xinput.lib
Vfw32.lib

FIRST - I will show you how to put together the skeleton for a DirectX game project and I'll use a lot of definitions and functions that might be confusing at first - but keep in mind I will explain more later.
Once the skeleton is complete - then we'll work in progressive stages building and experimenting as we add more to the actual game itself.


Step 1: open Visual Studio - select:  File>>New>>Project.

Step 2: select: Visual C++>>Win32>>Win32 Project and beside "Name:" make a name for your project (ie: MyGame) - click NEXT then choose "windows application" and choose "empty project" and click FINISH

Step 3: first we'll need a list of headers (.h files) that our software will need - these tell the compiler what we're gonna be using and what to expect so it knows how to build the final program.

select File>>New>>File and under Visual C++ category - select: Header File (.h) and click OPEN

(if you want you can go into Tools>>Options>>Fonts and Colors and adjust the colors of the various display items to suite your tastes -- I usually use a black background and special colors for strings and numbers and such so it's easier to find my way around the code -- [and white backgrounds give me a headache] ;) )

Paste in the following code into your new .h file and if you want you can go ahead and save the file now as "headers.h" ...basically this tells the compiler just to use what it needs to and behave the way we want.

#define WIN32_LEAN_AND_MEAN
#if (_WIN32_WINNT < 0x0501)
#define _WIN32_WINNT 0x0501
#endif
#define
STRICT

//make sure to load the correct library (if in debug mode or relase mode)
#ifdef
_DEBUG
#define D3D_DEBUG_INFO
#pragma comment(lib, "d3dx9d.lib")
#else
#pragma comment(lib, "d3dx9.lib")
#endif
#pragma comment(lib, "d3d9.lib")


#define DIRECTINPUT_VERSION 0x0800

Now we'll add some headers to tell the compiler what library functions we'd like to use in our code. (note: we might not actually need to use Direct Input -- and using DirectX 9 for XP compatability)

#include <d3dx9.h>
#include <Dxerr.h>
#include <windows.h>
#include <mmsystem.h>
#include <stdio.h>
#include <time.h>
#include <tchar.h>
#include "resource.h"
#include "main_defs.h"
#include "startup.h"
#include "GameInput.h"
#include "math.h"
#include "graphics.h"
#include "game_structs.h"

char g_str[9999];   

// F A T A L E R R O R 1 (shuts down d3d, closes the window, and shows errors if something goes wrong)
void FatalError(const char * error_msg) {
  end_d3d(g_gpu,g_d3d);
  END_WINDOW
  OutputDebugString( error_msg );
  ShowCursor(TRUE);
  OutputDebugString(
"\n");
  MessageBox(NULL,error_msg,"Game Debug",MB_OK ); exit(5);
}
// D I S P L A Y P R O B L E M L I S T (made this handy function for showing some error messages)
__declspec(dllexport) BOOL CALLBACK DisplayProblemList(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) {
   PAINTSTRUCT paintst;
  ShowCursor(TRUE);
  HDC hDC=BeginPaint(hdlg, &paintst); 
RECT rcClient;
  GetClientRect(hdlg, &rcClient);
int nOldBkMode = SetBkMode(hDC, TRANSPARENT);
  COLORREF clrOldTextColor = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  DrawText(hDC, Problem, -1, &rcClient, DT_CENTER | DT_VCENTER);
  SetTextColor(hDC,clrOldTextColor); SetBkMode(hDC, nOldBkMode); EndPaint(hdlg, &paintst);

  if (message == WM_COMMAND) {EndDialog(hdlg,1); return(TRUE);} return(FALSE);
}
//coded this one ugly I know but it takes up less space this way :p

g_str is a handy global variable(can be used anywhere in our program) that holds text strings for whatever we feel like. I chose to make it really long (9999 characters) but you could just use something like 500 or so.

And.. save as "headers.h". The d3dx9 header is so we can use d3dx helper functions(which are way awesome). The ones in quotes are custom headers which we haven't made yet.

I made a handy DisplayProblemList function which can report errors when the program closes in its own window using a dialog resource(the callback function redraws it and waits for OK click to close). To setup the resource:
View Solution Explorer -- expand "resource files" and click on your new .rc file -- right click on it and hit "open" -- right click on it and click "Add resource" and go into Dialog and use dialog bar and adjust the size by pulling down on those little dot things aroung the dialog box. Maybe just make it big enough for a few lines or so of text. Click on TO DO: layout dialog bar or whatever it says and just hit delete - change title bar to true - change border to dialog frame - change caption to "Program Terminated" - client edge to true - static edge to true - style to popup - set system_modal to true - set visible to true - set position: center to true -- now in toolbox under dialog editor - click button and add a button to the center bottom part of your dialog box(maybe toggle the grid on first)- click to select it - change the caption to OK - change horizontal alignment to center - set default button to true - change the ID to IDC_OK1 -- your .rc file and resource.h files will be updated automatically. This is what you might want it to look like:

DisplayProblemList Dialog Box

We'll program this only to be active in the debug version of the game. I'll also use a simple file report trick to catch bugs that could cause a system crash so we at least no what happened last time the program exploded on us ;p

Few things to keep in mind when programming a game:
ALWAYS make sure you allocate enough memory for your pointers always beware of infinite loop possibilities.
For example lets say you added snow and only expect about 100 snowflakes so you do this:

SNOWTYPE snowflakes[101];   //<--(should pad with one extra so 101 instead of 100)

... but then you later decide the snow generator should make 200 snow -- big trouble...
If you're not sure -- just make it big - ie: SNOWTYPE snowflakes[1001];
Sometimes you might wanna use a define for loops like

#define SAFE_DO do { if(KEYPRESS(ESCAPE) break;
#define SAFE_WHILE if KEYPRESS(ESCAPE) break; } while

a=0;
SAFE_DO {
    a++;
}SAFE_WHILE(a<100); //allows user to press escape to abort an infinite loop (in case one happens)

But as long as you're careful - simple loops like this are fine:

a=0;
do {
    a++;
}while(a<
100);

This works provided you've already coded the KEYPRESS definition (which we'll do shortly).

If you remembered to save headers.h - go into solution explorer and right click headers>>Add>>Existing Item -- and click "headers.h" and click ADD. This just makes it easier to navigate to different .h files using the solution explorer.

Step 4:
We'll need a maindefs.h header file where we'll store definitions and function protocols which tell the compiler what we mean when we use certain instructions -- we can make our own shortened instructions this way and save a lot of time and prevent possible confusion and reduce the size of our code

Right click headers>>Add>>New Item - Click "Header File(.h)" and type the name "main_defs" and click ADD.

Most of these defines are basically just substitute words to shorten bits of code and waste less time typing stuff out.
ER - if something fails and the first character in Problem isn't 1 then it's a fatal error and the program must exit.
ID3D - just a substitute word I made telling the compiler which vars to pass when setting up DirectX/D3D
INIT_WINDOW - shortens setting up the window - basically calls init_window function (which we'll program later)
END_WINDOW - just calls end_window -- just made this to simplify the code a bit
INIT_D3D - commented out so it isn't used - but was going to use it for more complicated setups
INIT_D3D_SIMPLE - calls init_d3d_simple function and remembers the display's half_width and half_height -- notice the use of ER to simplify coding a fatal error reaction. I'll show you how to program this function later...

Note: Problem is a string of characters for holding information used in DisplayProblemList and PROBLEM (which we'll add later) is a define which checks to see if there's already a problem to report before reporting a problem -- the reason I do this is because sometimes the first thing to cause a problem will spring up other problems before the program exits -- we are only interested in the initial cause...

#include "math.h"
// D E F I N I T I O N S

//initializing the window and graphics card
#define ER {if (!r) {if (*Problem!='1') FatalError(Problem);} } //ER for closing on a serious error
#define ID3D g_d3d,g_hwnd,g_instance,g_width,g_height,g_bpp,g_common_format,g_gpu,g_zbuffer,d3dpp
#define INIT_WINDOW bool r; g_instance=hInstC; r=init_window(g_hwnd,g_instance);
#define END_WINDOW end_window(g_hwnd,g_instance);
#define INIT_D3D_SIMPLE if (r) {r=init_d3d_simple(ID3D); ER g_half_width=g_width/2; g_half_height=g_height/2;}
#define END_D3D end_d3d(g_gpu,g_d3d);

//errors:
#define BEGIN_MEMORY_LEAK_CHECK _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_WNDW );_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_WNDW );_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_WNDW );_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );_CrtMemCheckpoint( &s1 );
#define SHOW_MEMORY_LEAK_DATA OutputHeading( "Examine outstanding allocations (dump memory leaks)" );_CrtDumpMemoryLeaks( );OutputHeading( "Program exits without freeing a memory block" );SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF );

BEGIN_MEMORY_LEAK_CHECK - (note: you'd have to use the \ character each time you start a new line when using #define)-- I actually have this all on one line in mine - It's well tested - I know it works so there's no need to concern ourselves with how this works right now - basically what this does is use some of microsofts functions to test for and report to us any memory leaks -- which is basically just memory that we've allocated to our program and forgot to free-up when exiting the program -- memory leaks can cause a lot of complications so we want to watch out for those.
SHOW_MEMORY_LEAK_DATA - this calls the functions that show the results of the memory leak testing in popup windows(OutputHeading is a function we'll make below in main_defs.h) -- in the final release version of our program we'll disable these by turning off a debug definition

HANDLE_LOST_DEVICES - this could have been done as a function - but whatever -- it substitutes code that checks for a lost device(graphics card), waits for a few microseconds, tests for it's availability again - tries again later if it still fails(returns so it doesn't try to render) -- when available - if it was used by another program or something - it cleans up all the memory used for graphics -- resets - and recreates the depthstencilsurface (allocates memory) and reloads graphics onto the card. This definition won't work everywhere - we'll just use it in the main render loop -- I just threw it in here to simplify some code later... I'll explain more about setting up the card and depth stencil surface later...

#define HANDLE_LOST_DEVICES(p1,p2)\
    if(DeviceLost) { Sleep(
100 );\
        if(FAILED(ghr=g_gpu->TestCooperativeLevel())) {\
            if(ghr==D3DERR_DEVICELOST) { }\
            if(ghr==D3DERR_DEVICENOTRESET) {\
                CleanupGraphics(); p1\
                ghr=g_gpu->Reset(&d3dpp);\
                HANDLE_RESET_ERRORS\
                SetCurrentDirectory(g_current_directory);\
                g_gpu->CreateDepthStencilSurface(g_width,g_height,D3DFMT_D16,D3DMULTISAMPLE_NONE,0\
                ,TRUE,&g_zbuffer,NULL);
\
                LoadGraphics(true); p2 \
           }\
       } DeviceLost = false;\
   }

Note that p1 and p2 are for freeing and loading extra graphics or resources - normally I would specify HANDLE_LOST_DEVICES( , ) - just leaving them blank with a comma in the middle. Otherwise you might want to do something like this for items not freed or loaded in CleanupGraphics or LoadGraphics:
HANDLE_LOST_DECICES( SAFE_RELEASE(texture.tx) , texture.LoadTexture(file) );

#define HANDLE_RESET_ERRORS if(FAILED(ghr)) { REPORT("Unable to reset device"); PROBLEM("Unable to reset device") switch (ghr) { case D3DERR_DEVICELOST: PROBLEM("(Reset FAIL) D3DERR_DEVICELOST") break; case D3DERR_DRIVERINTERNALERROR: PROBLEM("(Reset FAIL) D3DERR_DRIVERINTERNALERROR") break; case D3DERR_OUTOFVIDEOMEMORY: PROBLEM("(Reset FAIL) E_OUTOFVIDEOMEMORY") break; case D3DERR_INVALIDCALL: PROBLEM("(Reset FAIL) D3DERR_INVALIDCALL") break; } }

HANDLE_RESET_ERRORS -- if something went wrong in resetting the graphics device - prepare to show those errors on exiting the program and report to debug.txt file what the latest problem was (note this is used by HANDLE_LOST_DEVICES - I put it in after but the compiler doesnt have any trouble with this cuz it's a define)

// definitions used for 3D vertices and other 3d stuff
#define ALLOC(p1,p2) {p1 = new p2; if (p1==NULL) FatalError("Unable to allocate memory for " #p1 "(type: " #p2 ")\n");}

ALLOC - just shorter way to allocate memory for something and check to see if it worked (the # symbol in a define like #p1 combines whatever was used in ALLOC (ie: ALLOC(blabla, wasabi)) with the other string parts so it would say: Unable to allocate memory for blabla (type: wasabi) ) -- (the \n is just means start a new line)

CREATE_LIGHT - just a shorter way of entering all the vars for a light - and enabling it (used for 3D stuff)
#define CREATE_LIGHT(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15, \
p16,p17,p18,p19,p20,p21,p22,p23,p24,p25,p26,p27,p28) {ZeroMemory(&p1,sizeof(D3DLIGHT9));p1.Type=p2; \
p1.Diffuse.r=p3;p1.Diffuse.g=p4;p1.Diffuse.b=p5;p1.Diffuse.a=p6;p1.Ambient.r=p7;p1.Ambient.g=p8; \
p1.Ambient.b=p9;p1.Ambient.a=p10;p1.Specular.r=p11;p1.Specular.g=p12;p1.Specular.b=p13;p1.Specular.a=p14; \
p1.Direction.x=p15;p1.Direction.y=p16;p1.Direction.z=p17;p1.Position=D3DXVECTOR3(p18,p19,p20);p1.Range=p21;\
p1.Attenuation0=p22;p1.Attenuation1=p23;p1.Attenuation2=p24;p1.Falloff=p25;p1.Theta=p26; \
p1.Phi=p27;g_gpu->SetLight(p28,&p1);g_gpu->LightEnable(p28,TRUE);}

The D3DLIGHT9 structure has a bunch of parts that control the light. Ambient is minimum lighting, diffuse is the main light colors of interest to us - specular is for shine, direction is which way the light is pointing, position is where it is, attenutation is how fast it dims into the distance, falloff and theta and phi control how wide(circular radius) it is and how it dims toward the edge of that radius. SetLight inputs the light onto the graphics card. LightEnable turns it on.

CREATE_VERTEX_BUFFER - Since I like to mess around with the vertex buffer a lot and usually use simple 3D objects - I leave it as DYNAMIC so I can lock the buffer and make changes to it -- basically the vertex buffer holds the coordinate points for all the polygons that make up a 3D object. (you can look up the different flags and parameters for different results in the directX SDK documentation)

#define CREATE_VERTEX_BUFFER(p1,p2,p3) {ghr=g_gpu->CreateVertexBuffer((UINT)(p1), D3DUSAGE_DYNAMIC, p2, D3DPOOL_SYSTEMMEM, p3,NULL); if (FAILED(ghr)){if (ghr==D3DERR_INVALIDCALL) FatalError("Unable to create vertexbuffer: D3DERR_INVALIDCALL");if (ghr==D3DERR_OUTOFVIDEOMEMORY) FatalError("Unable to create vertexbuffer: D3DERR_OUTOFVIDEOMEMORY");if (ghr==E_OUTOFMEMORY) FatalError("Unable to create vertexbuffer: D3DERR_E_OUTOFMEMORY");FatalError("Error creating vertexbuffer");}}
#define CREATE_INDEX_BUFFER(p1,p2) {ghr=g_gpu->CreateIndexBuffer((UINT)(p1), D3DUSAGE_DYNAMIC, D3DFMT_INDEX32, D3DPOOL_SYSTEMMEM, p2,NULL); if (FAILED(ghr)){if (ghr==D3DERR_INVALIDCALL) FatalError("Unable to create indexbuffer: D3DERR_INVALIDCALL");if (ghr==D3DERR_OUTOFVIDEOMEMORY) FatalError("Unable to create indexbuffer: D3DERR_OUTOFVIDEOMEMORY");if (ghr==E_OUTOFMEMORY) FatalError("Unable to create indexbuffer: D3DERR_E_OUTOFMEMORY");FatalError("Error creating indexbuffer");}}

CREATE_INDEX_BUFFER - sometimes this optimization might not be needed but usually should be - basically an index buffer holds a list of indices - an index number in that list refers to a vertex in the vertex-list -- so if a vertex is for example at the tip of a pyramid - it may belong to 3 or 6 or more polygons which share that point -- so if the vertex position has already been rotated and positioned - why recalculate that for every polygon? - that's where the index comes in -- ie: if index[25]=6 then we want vertex[6]...

#define LOCK_VERTEX_BUFFER(p1,p2,p3,p4) {if (FAILED(p1->Lock(p2,p3,p4,0))) {FatalError("Error locking vertex buffer");}}
#define LOCK_INDEX_BUFFER(p1,p2,p3,p4) {if (FAILED(p1->Lock(p2,p3,p4,0))) {FatalError("Error locking index buffer");}}
#define FILL_VERTEX_BUFFER(p1,p2,p3,p4,p5) {i=p1;do{memcpy((p5+((size_t)i*sizeof(p3))),p4[i],sizeof(p3));i++;}while(i<(p2));}
#define UNLOCK_VERTEX_BUFFER(p1) {if (FAILED(p1->Unlock())) FatalError("Unable to unlock vertex buffer");}
#define UNLOCK_INDEX_BUFFER(p1) {if (FAILED(p1->Unlock())) FatalError("Unable to unlock index buffer");}

The above defines are basically substitution code for locking and unlocking vertex and index buffers so one can mess around with their contents. Locking it puts it on the hardware for optimal processing -- unlocking allows you to mess around with the data in regular memory.

//2d drawing / 2d graphics stuff

LOAD_TEXTURE_NONPOW2(p1,p2) takes the filename and bitmap pointer and calls the D3DX function for making a texture(a bitmap basically) - I set it up to allow widths and heights that are non powers of 2 (a lot of cards used to need power-of-two sizes like 128x128 or 256x256 or 512x512 or 1024x1024 for example -- which from what I've heard are still faster to use on newer cards so you should try to use as much as possible) I'm allowing directX to manage the memory and using alpha(transparency), red, green, and blue channels - 8 bits for each for 32bit color. I don't need MIP maps cuz this is mainly 2D game stuff so I set that to 1. We may make one for 3D mips later(different bitmap detail for different distances) - don't need filters - g_gpu will be our global pointer to the graphics processor - I'll explain more later.... If something goes wrong - we check the ghr returned (global handle result variable) to see what happened and report the problem (FATAL is another definition that I'll include later)

#define LOAD_TEXTURE_NONPOW2(p1,p2) \
    if (p2!=NULL) REPORT(" " #p2 " not NULL"); \
    if (FileExists(p1)) { \
        ghr=D3DXCreateTextureFromFileEx(g_gpu, p1, D3DX_DEFAULT_NONPOW2, \
                D3DX_DEFAULT_NONPOW2, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, \
                D3DX_FILTER_NONE, D3DX_FILTER_NONE, 0, NULL, NULL, &##p2); \
        if (ghr!=D3D_OK) { if (ghr==D3DERR_NOTAVAILABLE) PROBLEM("Can't create texture from file: D3DERR_NOTAVAILABLE") if (ghr==D3DERR_OUTOFVIDEOMEMORY) PROBLEM("Can't create texture from file: D3DERR_OUTOFVIDEOMEMORY") if (ghr==D3DERR_INVALIDCALL) PROBLEM("Can't create texture from file: D3DERR_INVALIDCALL") if (ghr==D3DXERR_INVALIDDATA) PROBLEM("Can't create texture from file: D3DXERR_INVALIDDATA \nCan't find file.") if (ghr==E_OUTOFMEMORY) PROBLEM("Can't create texture from file: E_OUTOFMEMORY") FATAL("D3DXCreateTextureFromFile",Problem) } \
    }
#define LOAD_TEXTURE(p1,p2) \
    if (p2!=NULL) REPORT(" " #p2 " not NULL"); \
    if (FileExists(p1)) { \
        ghr=D3DXCreateTextureFromFileEx(g_gpu, p1, D3DX_DEFAULT, D3DX_DEFAULT, \
            1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, 0, \
            NULL, NULL, &##p2); \
        if (ghr!=D3D_OK) { if (ghr==D3DERR_NOTAVAILABLE) PROBLEM("Can't create texture from file: D3DERR_NOTAVAILABLE") if (ghr==D3DERR_OUTOFVIDEOMEMORY) PROBLEM("Can't create texture from file: D3DERR_OUTOFVIDEOMEMORY") if (ghr==D3DERR_INVALIDCALL) PROBLEM("Can't create texture from file: D3DERR_INVALIDCALL") if (ghr==D3DXERR_INVALIDDATA) PROBLEM("Can't create texture from file: D3DXERR_INVALIDDATA \nCan't find file.") if (ghr==E_OUTOFMEMORY) PROBLEM("Can't create texture from file: E_OUTOFMEMORY") FATAL("D3DXCreateTextureFromFile",Problem) } \
    }
//^^if a keycolor is needed(instead of just alpha channels), use D3DCOLOR_XRGB(r,g,b) after filter settings^^

LOAD_TEXTURE(p1,p2) - use for loading textures/bitmaps - fast power-of-two textures ie: 512x512, 1024x1024 -- same as other loader except it only allocates memory for sizes that are a power of 2 (note: don't worry about keycolor comment for now - keycolor is a color that won't show up when you render the image - totally see-through parts)

I'm actually going to add a texture class so we can be sure all resources are freed when the program exits (via destructor)... otherwise it is possible to miss something which can cause a memory leak.

#define DRAW_SPRITE(tex,rec,poz) if (tex!=NULL) g_sprite->Draw(tex,rec,NULL,poz,g_screen_tint);
#define DRAW(tex,rec,poz) if (tex##.tx!=NULL) g_sprite->Draw(tex##.tx,rec,NULL,poz,g_screen_tint);
#define DRAWC(tex,rec,poz,clr) if (tex##.tx!=NULL) g_sprite->Draw(tex##.tx,rec,NULL,poz,clr);

Some useful 2D drawing definitions - first one takes texture, rectangle and position - 2nd one is the same but is for our personalized texture class - which we'll make later. We'll use .tx to hold the actual texture/bitmap.
DRAWC is the same as DRAW except allows specifying a tint color.

// text
#define PRINT_TEXT(p1) g_font->DrawText(g_sprite,p1,-1,&text_position,DT_LEFT| DT_TOP | DT_WORDBREAK,text_color);
#define PRINT_TEXT2(p1) g_font2->DrawText(g_sprite,p1,-1,&text_position,DT_LEFT| DT_TOP | DT_WORDBREAK,text_color);
#define PRINT_TEXT_D(p1,p2,p3) g_font->DrawText(g_sprite,p1,-1,&text_position,DT_LEFT| DT_TOP | DT_WORDBREAK,text_color); text_position.left=p3; sprintf_s(g_str,"%d",p2);g_font->DrawText(g_sprite,g_str,-1,&text_position,DT_LEFT| DT_TOP | DT_WORDBREAK,text_color);
#define TEXT_POSITION(p1,p2) text_position.top=p2;text_position.left=p1;text_position.bottom=g_height;text_position.right=g_width;
#define PRINT_TEXT_EXT(p1,p2,colr,txt) text_position.top=p2;text_position.left=p1;text_position.bottom=g_height;text_position.right=g_width; text_color=colr; g_font->DrawText(g_sprite,txt,-1,&text_position,DT_LEFT| DT_TOP | DT_WORDBREAK,text_color);
#define PRINT_T(p1,p2,colr,txt) text_position.top+=p2;text_position.left=p1;text_position.bottom=g_height;text_position.right=g_width; text_color=colr; g_font->DrawText(g_sprite,txt,-1,&text_position,DT_LEFT| DT_TOP | DT_WORDBREAK,text_color);

The above text printing definitions could come in handy for printing text in a few different ways. I just made these to make the process of using fonts a little quicker and cleaner. We'll probably use PRINT_TEXT_EXT the most(position, color, text). PRINT_T is the same but automatically acts like it adds a carriage return(or more based on p2). PRINT_TEXT_D allows printing something like "the number is:", n (where the last parameter is the offset from the margin) - TEXT_POSITION determines where text will appear for this and for PRINT_TEXT..

// variable setting
#define SET_RECT(p,p1,p2,p3,p4) p.left=p1;p.top=p2;p.right=p3;p.bottom=p4;
#define VEC_ZERO(p) p.x=0; p.y=0; p.z=0;
#define STR_TO_INT(p) atoi(p);

Just some more definitions which I use which clarfiy the code for me. SET_RECT sets a rect struct, VEC_ZERO sets a vector to 0,0,0 and STR_TO_INT is atoi which converts int to characters - which I find easier to remember.

Prototypes are basically just ways of telling the compiler what to expect to see later as it compiles and what the rules are for passing variables between functions (without the prototype - if the compiler hasn't seen the actual function before it will stop compiling and be all confused and complain at you and stuff)

//P R O T O T Y P E S
void InitRenderVars();
void LoadGraphics(bool restore_all);
void Cleanup();
void CleanupGraphics();
void InitVars();

We'll need to add these later: (won't hurt to add them now):

void GameScroll(float x, float y);
void UpdateMousePos(LPPOINT xy);
bool EscapeKey(bool &pressed);
void load_tilemap();
void UpdateViewMatrix();

We'll code the actual functions later. InitRenderVars will setup any lights, 3D objects, and viewing perspective stuff and CleanupGraphics will release allocated memory for pointers or objects or whatever we have taking up memory in the computer. LoadGraphics and CleanupGraphics load level graphics(as needed) and release memory used by graphics... InitVars is just somewhere we can set the initial value of variables (ie: num_monsters=0;)

//EXTERNAL VARIABLES
extern "C" char * Problem = "0 errors ";
extern bool g_exit_game = false;
extern int g_WindowReactivate = 0;
//for windows key disable:
extern HHOOK g_hKeyboardHook = NULL;
extern BOOL g_bFullscreen = true;
extern BOOL g_bWindowActive = false;
//mouse inputs
extern bool left_mouse_clicked=false;
extern bool find_new_joysticks=false;
extern VEC mouse_pos = D3DXVECTOR3(0,0,0); //VEC will be defined in math.h as a D3DXVECTOR3

The above global variables need to be used in more than one C++ file/module - so I declare them to be extern -- all extern variables must be initialized (ie: = 0; or = false;) here or it can cause issues - I also declare the existence of these as "extern" inside each module(C++ file) that uses them. "Problem" - a string for showing errors when the game exits, g_exit_game is true if the game must exit now, g_WindowReactivate tells main module that we are reactivating the window(if it was deactivated before - like if someone hit Alt+Tab and then returned to the game) - g_hKeyboardHook is used when disabling the annoying windows key(cuz it interferes with game play), g_bFullscreen(should always be true for us) determines whether the window is in fullscreen mode, and g_bWindowActive is useful for pausing the game if another program interupts us or someone uses Alt+Tab.. left_mouse_clicked is checked in the title screen where the mouse is used to see if the user clicked on a button or something, find_new_joysticks tells us to search for new joysticks attached to the computer because there has been hardware added.

//GLOBAL VARIABLES
HRESULT ghr = D3D_OK;
HINSTANCE g_instance;
HWND g_hwnd = NULL;
LPDIRECT3D9 g_d3d = NULL;
LPDIRECT3DDEVICE9 g_gpu = NULL;
D3DPRESENT_PARAMETERS d3dpp;
LPDIRECT3DSURFACE9 g_zbuffer = NULL; // the pointer to the z-buffer
DWORD g_bpp; //pixel depth
int g_width=800,g_height=600,g_half_width=400,g_half_height=300;
D3DFORMAT g_common_format; //color format
DWORD g_background_color=0;

The above variables are mainly used in multiple functions in the main module and are also used in startup.cpp when we are setting up the hardware/display for the game.
ghr - these are used to determine what kind of error happened when the computer returned from a function
g_instance - handle of the current instance of this application/game (there should only be 1 instance of the game)
g_hwnd - handle of the window/application
g_d3d - pointer to the main directX interface
g_gpu -- pointer to the graphics device object -- we'll be using this a lot
g_zbuffer - pointer to the z-buffer -- and memory space(buffer) that stores information about depth of each screen pixel into the 3D world. Only the pixels closest to us will be rendered.
g_width, g_height -- dimensions/resolution of the display
g_common_format - color format: ie: A8R8G8B8 (alpha - 8bits, red 8bits, green 8bits, blue 8 bits)
g_background_color - clear-screen color

#define MY_CUSTOM_VERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX1)
#define TRANSFORMED_VERTEX (D3DFVF_XYZRHW|D3DFVF_TEX1)
#define RECTANGLE_VERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)

(we will use these flags when setting up our vertex list so direct 3D knows what format the data will come in)
MY_CUSTOM_VERTEX - the flags here show that each vertex in my vertex list will include x,y,z values for a 3D point, a normal(a vector that shows which way the point is facing - used in lighting/shine), a diffuse color, and a UV texture coordinate (where on the bitmap/texture does this point sample from). When rendering each polygon (usually made of 3 of these vertices) - it interpolates between the 3 points accross the surface to determine how it should be rendered.
TRANSFORMED_VERTEX - use for lists of vertices that don't need transformation
RECTANGLE_VERTEX - was using this for rendering 2D colored rectangles in 3D space - but we might not need this..

struct stMyVertex{
    FLOAT x, y, z;
    FLOAT nx,ny,nz;
    DWORD colour;
    FLOAT tu, tv;
};
struct stTransformedVertex{
    FLOAT x, y, z, rhw;
    FLOAT tu, tv;
};
struct stRectangleVertex{
    FLOAT x, y, z, rhw;
    DWORD colour;
    FLOAT tu, tv;
};

stMyVertex is the structure of a typical 3D vertex (for 3D stuff this is mainly what we'll use)

typedef struct {
    VEC Position; // position in world space
    VEC Target; // camera target
    float h_speed;
    float v_speed;
    float xa,ya; // camera rotation angles
    float uni_scale;
    D3DXMATRIX RotationMatrix;
    D3DXMATRIX TranslationMatrix;
    D3DXMATRIX ScaleMatrix;
} VIEWDESC;
VIEWDESC ViewDesc;

First I declare the structure of a VIEWDESC as I call it - then define the variable ViewDesc as being one of those. It is used to describe where the camera is, where it points, how it moves, and contains matrices which keep track of transformation/translation calculations. In this tutorial, since it is a sidescrolling gane - I'm gonna set the camera to be stationary for now and move the world passed the camera. I might add some neat tricks later though.

// S T R U C T S
typedef struct {
    VEC min,max,center,wide_high_deep;
    float radius;
} stBounds;

An stBounds structure will contain info about the collision region of a 3D object. min, max, and wide_high_deep store information about a tightly fitting bounding box around the object or sub-object and radius is used to keep track of its outmost bounding sphere -- an imaginary sphere that can fit around the entire object)

typedef struct {
    float U, V;
} stTexCoord;

stTexCoord - just a struct that contains a U and V coordinate - which together determine where in a texture/bitmap we are sampling from.
MOSTLY - don't worry about this 3D object/mesh stuff too much for now -- most of it either won't be used or won't be used until much later. It's handy to have for conversion or app development so I thought I'd throw it in here. It's likely to come in handy eventually.
stFace - a structure which holds information about a single polygon
stObject - a sub-object or part of a mesh
stPolyCandidate - a polygon that qualifies as visible
stMeshSystem -
Holds the objects that make up the final mesh (ie: main hero)

typedef struct {
    float left,right,top,bottom;
} FRECT;

I just added FRECT so I can have floating point RECT structs instead of just ones that use LONG vars (less casting to floating point or to LONG)

If you don't feel like it - you won't need to include these in your main_defs.h file... we probably won't use these:

typedef struct {
    DWORD a, b, c;
    bool removed;
    float patch_width, patch_height;
    float patch_x_offset, patch_y_offset;
    float px1,px2,px3,py1,py2,py3;
    float nx1,nx2,nx3,ny1,ny2,ny3;
    float lmo,rmo,umo,dmo;
} stFace;
typedef struct { //SUB-OBJECTS OF MESHSYSTEMS
    DWORD NumVertices;
    int NumColoredVertices;
    DWORD NumFaces;
    DWORD NumTexturedVertices;
    int NumTexturedFaces;
    char *ObjectName;
    stFace **FaceList;
    VEC **FaceNormal;
    VEC **VertexList;
    VEC **VertexNormal;
    stTexCoord **UV;
    stFace **UVFaceList;
    stBounds **PolyBounds;
    VEC **VertexColors;
    DWORD MaterialRef;
    VEC center,min,max,wide_high_deep;
    float radius;
    int min_vertex,num_indices;
    DWORD start_index,start_vertex;
    UINT vb_offset;
    UINT vb_offset_m;
    bool removed;
} stObject;
typedef struct {
    UINT a, b;
    float average_z;
    VEC v1,v2,v3;
    VEC s1,s2,s3;
    VEC zv1,zv2,zv3;
    bool removed;
    D3DXPLANE plane;
}stPolyCandidate;
typedef struct {
    DWORD num_objects; //num sub-objects
    stObject **ob1;
    stBounds **SystemBounds;
    DWORD num_candidates;
    stPolyCandidate *poly_candidates;
    VEC pos;
    int GrandVertexCount; //combined vertex count for all objects
    int GrandFaceCount; //face count " "
} stMeshSystem;
stMeshSystem sys;
//(all elements in this need to be allocated dynamically - at runtime [might show you later])

But... we WILL NEED these however:

// D E B U G ----------------------------------------------
#include <string.h>
#include <malloc.h> // memory leak protection
#include <crtdbg.h>
#define SET_CRT_DEBUG_FIELD(a) _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
#define CLEAR_CRT_DEBUG_FIELD(a) _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
_CrtMemState s1;
void OutputHeading( const char * explanation ) {
_RPT1( _CRT_WARN,
"\n\n%s:\n**************************************\
************************************\n"
, explanation );
}
//----------------------------------------------------------

^^These will be needed for memory leak protection^^
(You may remember we used OutputHeading in the SHOW_MEMORY_LEAK_DATA) - it's the function that shows memory leaks in a dialog box when the program quits - if there are none - it will be a blank dialog box. Don't forget to save (main_defs.h) :p

Well hopefully that wasn't too confusing -- it'll all come together when you see how we will use these definitions, structures, and functions..
Basically the idea is in the main module (which I usually call main.cpp) we will have a layout that goes something sort of like this:

#include "headers.h" //<--this contains most of our headers (just makes our main module shorter)
#include "debug.h" //<--another custom header which will have some stuff to help us report bugs to file

// G L O B A L   V A R I A B L E S
//JOYSTICK device variables will go here
//Font variables will go here (for DirectX font display stuff)
bool DeviceLost=false; //<--needed to keep track of lost graphics situation if game gets interrupted and stuff
LPD3DXSPRITE g_sprite = NULL; //<--d3dx sprite interface - will make drawing and animating 2D sprites easy
D3DLIGHT9 g_light; //<--main light we'll use (good for 3D stuff)
//MATRIX/matrices will go here - some of these will be for transforming objects in 3D space and some used for perspective transformation (from 3D coords to what's on screen) - I'll also have a matrix for controlling sprite animation in 2D - we'll call it: g_matrix_2d
//LPDIRECT3DTEXTURE9 <--a bunch of these will hold images/textures/bitmaps - whatever you want to call them
//Sound variables
//timing variables ... etc...
BEGIN_SCENE and END_SCENE definitions (which just make setting up a scene for rendering look better and simpler)

// M A I N (this is where the program starts)
int WINAPI WinMain(HINSTANCE hInstC,HINSTANCE hInstP,LPSTR lpCmdLine,int nCmdShow) {
    BEGIN_MEMORY_LEAK_CHECK;
    RESET_REPORT; //(for reporting errors to file)

    INIT_WINDOW;
    Disable_Windows_Key();
    INIT_INPUT;

    INIT_D3D_SIMPLE;

    InitRenderVars();
    LoadGraphics(true);
    InitVars();

    //----MAIN_LOOP---->
    while(!g_exit_game) {          
         INPUT_MSG;
        //(adds new gaming device if needed)
        //(resets stuff if window lost focus - ie: another program interrupted the game)
        //timer stuff - so the frame rate stays constant and the animation looks smooth
        //ALL GAMER INPUT GOES HERE!!!
        if (KEYPRESS(ESCAPE)) ExitGame; //for now
        render(); //<--this function will show all our pretty graphics
     }//<----main_loop----

    CleanupGraphics();
    END_D3D
    END_WINDOW

    Renable_Window_Key();
    //show any problems here using DisplayProblemList
    SHOW_MEMORY_LEAK_DATA
  return 0;
}

So basically it first sets up the computer for testing for memory leak problems, then makes a blank file which it will report errors to and append new errors to the report if it finds more during code execution. Then it makes our window which is needed for any windows application and   END_WINDOW

    Renable_Window_Key();
    //show any problems here using DisplayProblemList
    SHOW_MEMORY_LEAK_DATA
  return 0;
}

So basically it first sets up the computer for testing for memory leak problems, then makes a blank file which it will report errors to and append new errors to the report if it finds more during code execution. Then it makes our window which is needed for any windows application and sets it up for full-screen mode. I disable the windows key although that is optional - it just makes playing certain games less frustrating. Then we setup all stuff we need to quickly get and process user input. Then we start Direct3D which will talk to the graphics card for us - we'll set it up for 800x600 resolution(or whatever valid display you want) - but you can change this so the user can select a display from a list of valid displays found by directx if you want. I might make a tutorial for that in the future. We then setup our graphics variables and load images into texture memory. We'll also add file loading for levels and sounds and music later.
CleanupGraphics - just free up any used memory and release directX stuff. End_d3d shuts down Direct3D and End_Window shuts down our window - then we just renable windows key and show any memory leak information (blank if none).

STEP 5:

Go into Solution Explorer -- right click Headers>>Add>>New Item - click HeaderFile(.h) and call it common and add the following code (and save):

These will be commonly used in all the modules so I called it common.h and include "common.h" in most of our .cpp files

#ifndef COMMON_H
#define COMMON_H

#include "debug.h"

#define SAFE_RELEASE_FINAL(x) {if(x) {if (ULONG vsvs=x->Release()>0) \
    REPORT_D(
"reference > 0 -- "#x,(DWORD)vsvs); x=NULL;}}
#define SAFE_RELEASE(x) {if(x) {x->Release(); x=NULL;}}
#define SAFE_DELETE(p) {if(p) {delete (p); (p)=NULL;}}
#define SAFE_DELETE_ARRAY(p) {if(p) {delete []p; p = NULL;}}
//paranoid safety stuff:
#define SAFE_DO do { if(KEYPRESS(F12)) break;
#define TEST_DO(p) do { if(KEYPRESS(F12)) {REPORT(p); break;}
#define SAFE_WHILE if(KEYPRESS(F12))break; }while
#define SAFE_DIV(p0,p1,p2) if (p2==0) p0=p1/0.000001f; else p0=p1/p2;

#ifndef PROBLEM
#define PROBLEM(p) if (Problem[0]=='0') {Problem=p; OutputDebugString(p);}
#endif
#define MAKEFOURCC(ch0, ch1, ch2, ch3) ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))

#endif

ifndef COMMON_H - basically just makes sure the compiler doesn't do this twice causing it confusion. debug.h we'll make soon - it will contain stuff for error reporting.

Basically these defines are a shortcut way of making sure we don't try to delete or free something that's already freed - cuz that could cause issues.. ;p

SAFE_RELEASE_FINAL - used when releasing for the last time - it reports if not all references to the object have been released which could be a problem (don't worry if sometimes it thinks g_d3d>0 or g_gpu>0 - you'll notice with directX debug reporting turned on that they were actually freed at the very end)
SAFE_RELEASE - release it if it is valid
SAFE_DELETE - delete an object (only if it has actually been allocated)
SAFE_DELETE_ARRAY -- delete an array(a list) of objects
PROBLEM(p) - this makes "Problem" hold the dialog of what the problem is - but only if it is the first cause of the problem(because that's most likely the cause of our problems) - DisplayProblemList will show it to us on exit

If using SAFE_DO or SAFE_WHILE - you can hold F12 (or whatever key u define) to break out of an infinite loop if one should appear to occur. Otherwise you made need to use Alt+Enter - go to Visual Studio and hit Shift+F5 if something else is causing the program to freeze up. SAFE_DIV should be used whenever you need to divide to prevent divide by zero errors (you may want to use a longer decimal place).

MAKEFOURCC is a way to convert color data which might come in handy - We usually use 1 byte(8 bits) for alpha, red, green, and blue -- which combine together as 1 32bit DWORD which represents the color for color_format: A8R8G8B8 - which is mostly what is used in games. Each channel can be from 0 to 255. IE: Red=255 means the red part of the color is at maximum. If it was red=128 and blue=128 -- that would make dark purple or r=255, b=255 would make bright purple (and zeros make black). Alpha controls see-through value - so you can see through it like colored glass.

STEP 6:

Go into solution Explorer -- right click Headers>>Add>>New Item and chose HeaderFile(.h) and call it debug and add the following code (and save):

//note that some of these I just put on one line but you can use \ to use multiple lines if you like.. Yes I know it's ugly - but I like it better this way -- takes up less space and takes less time to find stuff. We could use functions - but I like this better... but that's just me... (I also note that sometimes defines and inline sometimes result in faster code)

#define RESET_REPORT {FILE *eye=NULL; if (fopen_s(&eye,"debug.txt","w")!=0) PROBLEM("Unable to open debug.txt \n"); if (eye!=NULL) {if(fclose(eye)) {PROBLEM("debug.txt was not closed\n");}}}
#define REPORT_D(s,d1) {FILE *eye=NULL; if (fopen_s(&eye,"debug.txt","a")!=0) PROBLEM("Unable to open debug.txt \n"); fprintf_s(eye,"%s %d \n",s,d1);if (eye!=NULL) {if(fclose(eye)) {PROBLEM("debug.txt was not closed\n");}}}
#define REPORT_DDD(s,d1,d2,d3) {FILE *eye=NULL; if (fopen_s(&eye,"debug.txt","a")!=0) PROBLEM("Unable to open debug.txt \n"); fprintf_s(eye,"%s %d %d %d \n",s,d1,d2,d3);if (eye!=NULL) {if(fclose(eye)) {PROBLEM("debug.txt was not closed\n");}}}
#define REPORT_F(s,f1) {FILE *eye=NULL; if (fopen_s(&eye,"debug.txt","a")!=0) PROBLEM("Unable to open debug.txt \n"); fprintf_s(eye,"%s %f \n",s,f1);if (eye!=NULL) {if(fclose(eye)) {PROBLEM("debug.txt was not closed\n");}}}
#define REPORT_FFF(s,a1,a2,a3) {FILE *eye=NULL; if (fopen_s(&eye,"debug.txt","a")!=0) PROBLEM("Unable to open debug.txt \n"); fprintf_s(eye,"%s %f %f %f \n",s,a1,a2,a3);if (eye!=NULL) {if(fclose(eye)) {PROBLEM("debug.txt was not closed\n");}}}
#define REPORT_U(s,d1) {FILE *eye=NULL; if (fopen_s(&eye,"debug.txt","a")!=0) PROBLEM("Unable to open debug.txt \n"); fprintf_s(eye,"%s %u \n",s,d1);if (eye!=NULL) {if(fclose(eye)) {PROBLEM("debug.txt was not closed\n");}}}
#define REPORT_S(s,s1) {FILE *eye=NULL; if (fopen_s(&eye,"debug.txt","a")!=0) PROBLEM("Unable to open debug.txt \n"); fprintf_s(eye,"%s %s \n",s,s1);if (eye!=NULL) {if(fclose(eye)) {PROBLEM("debug.txt was not closed\n");}}}
#define REPORT(s) {FILE *eye=NULL; if (fopen_s(&eye,"debug.txt","a")!=0) PROBLEM("Unable to open debug.txt \n"); fprintf_s(eye,"%s \n",s);if (eye!=NULL) {if(fclose(eye)) {PROBLEM("debug.txt was not closed\n");}}}
#define SAY(s) {REPORT(s) PROBLEM(s)}
#define INIT_T {start_t=clock();}
#define REPORT_T(s) {end_t=clock();REPORT_U(s,(unsigned)(end_t-start_t)) }
#define FATAL(p1,p2) if (Problem[0]=='0') FatalError(p1); else FatalError(p2);

(
On final release we might make a release version of the code that has no REPORT stuff)
RESET_REPORT - creates a new file for writing our report to "debug.txt"
(one your debug.txt exists - it is handy to add it to your resource files for quick access)

REPORT_D - we can use this to check the value of an integer or DWORD when something funny is happening. It will append this to the debug.h file.
For example:
a=0;
do {
    REPORT_D("last value before fail: a = ",a);
    b=100/a; //<--can't divide by zero!!!!!! Watch out for these!!!
    a++;
}while(a<100);
Note that the above code could cause a crash - you may need to hit Alt+Tab and then shift+F5 a few times to abort.

So in the debug.txt (just go to file>>open and open it) we should see this(even if we had to reboot the computer):

last value before fail: a = 0

(of course unless you do did this: SAFE_DIV(b,100,a); //b=100/a
It would actually probably be better to do this (cuz somtimes a variable will pass through zero regardless):

#define SAFE_DIV(p0,p1,p2) if (p2==0) p0=p1/0.000001f; else p0=p1/p2;

REPORT_DDD - reports an explaination followed by 3 integers or words
REPORT_F - reports an explaination followed by a floating point number (ie: a = 0.0035f or something like that)
REPORT_FFF - reports 3 floats
REPORT_U - reports an unsigned (positive values only ie: unsigned int screen_width = 800;)
REPORT_S - reports 2 strings (ie: "Something seems weird with string: g_str = ","bubblebutters!" )
REPORT(s) - just use this to make a comment (like - "entering DrawTile function")
SAY(s) - this is useful if you'd like it to display it as a problem on exit and report the problem to file
INIT_T and REPOR_T combined allow us to analyze time passage in certain parts of some functions (good for optimization analysis)

Don't forget to save the file.

STEP 7:

Go Solution Explorer - right click HeaderFiles>>Add>>New Item - HeaderFile(.h) - name it math and add this code(and save):

//Math.h
#include<math.h>
#include<d3dx9.h>

We'll need math.h for using math functions like cos() and such - we'll also need the compiler to know about d3dx functions.

#define PLANE_LEFT 0
#define PLANE_RIGHT 1
#define PLANE_TOP 2
#define PLANE_BOTTOM 3
#define PLANE_NEAR 4
#define PLANE_FAR 5
#define NEAR_Z 1.0f
#define FAR_Z 4000.0f

The above are just values for clipping planes which are planes used for clipping objects and geometry that is outside of the viewing frustum(google this) - you might like to play around with the FAR_Z for clipping far objects.. These are largely used for 3D stuff and you don't really need to worry about them too much for now.

#define FCOS(p) (float)cos((double)p)
#define FSIN(p) (float)sin((double)p)
#define FSQRT(p) (float)sqrt((double)p)

For floating-point cosine or sine stuff, we'll just use regular cos or sin (and fsqrt for floating squareroot) - the above will come in handy if we need to use doubles(like a very precise float - much larger decimal place) for these with floating point results (we might not actually use them in this tutorial).

#define MAKE_VECTOR(p1,p2,p3) {p1.x=p2.x-p3.x; p1.y=p2.y-p3.y; p1.z=p2.z-p3.z;}
#define COPY_VECTOR(p1,p2) {p1.x=p2.x; p1.y=p2.y; p1.z=p2.z;}
#define PCOPY_VECTOR(p1,p2) {p1.x=p2->x; p1.y=p2->y; p1.z=p2->z;}

MAKE_VECTOR - if we want to make a vector from 2 other vectors(or in vertices in this case[just keep in mind that all these are - are 3 values - x,y,z -- depending on how we use them, we can say they are points(vertices) or distances(vectors)) -- just gets the difference between the two points to make a vector that connects the two.

This is useful for example if we had our game character at some point in this frame - and in the next frame we know where he will be(adding his traveling distance) - we make a vector between the 2 points and check to see if the vector passes through a barrier -- if it does then we stop him at the barrier - otherwise he'll go through the wall... ;d
This works in 2D too - we just pass 0(or 1 or whatever) for all the Z values(as long as they're the same).

COPY_VECTOR - just did this again to save some typing. It's easier to say:
COPY_VECTOR(vector1, vector2) (instead of going: vector1.x=vector2.x; vector1.y=vector2.y; vector1.z=vector2.z)
PCOPY_VECTOR is the same except that it takes a pointer to a vector.

#define RAND(n) ((float)(rand()%1000))/1000.0f*n
#define RAND_INT(n) (int)(((float)(rand()%1000))/1000.0f*n)

for making a random floating point number (very handy)
RAND(50) for example would create a random number between 0.0f and 50.0f.

float tile_distance(int a1, int b1, int a2, int b2);
float CosineInterpolate(float y1,float y2,float mu);

^^These are just prototypes to help out the compiler so it knows what functions to expect to find in math.cpp(which we'll make soon). It also makes these functions available to modules that #include"math.h"
tile_distance - returns the distance between tiles (a tile grid generally keeps track of where things are on screen and in the 2D game world - I'll explain more later...)
CosineInterpolate - useful for smoothly transitioning something from one point to another(like if we wanted to slide an image onto the screen nice and smooth-like -- I'll show this later)

STEP 8:

Go solution explorer and right click Header Files>>Add>New Item - HeaderFile(.h) and call it startup and paste the following code (and save):

#ifndef STARTUP_H
#define STARTUP_H
#include <windows.h>
#include <Winuser.h>
#include <d3dx9.h>
#include "common.h"

The ifndef part is used to prevent compiler confusion(like if this .h file is used in more than one module)
We'll need access to functions and definitions in windows.h, winuser and d3dx - and the "common.h" file we made.

//PROTOTYPES
bool init_window(HWND &g_hwnd,HINSTANCE &g_instance);
void end_window(HWND &g_hwnd,HINSTANCE &g_instance);

Functions for starting the window and ending it (which we'll make in startup.cpp)

bool init_d3d_simple(LPDIRECT3D9 &g_d3d, HWND &g_hwnd, HINSTANCE &g_instance,
int &g_width, int &g_height, DWORD &g_bpp, D3DFORMAT &g_common_format,
LPDIRECT3DDEVICE9 &g_gpu, LPDIRECT3DSURFACE9 &g_zbuffer,
D3DPRESENT_PARAMETERS &d3dpp);
void end_d3d(LPDIRECT3DDEVICE9 &g_gpu,LPDIRECT3D9 &g_d3d);

init_d3d_simple and end_d3d will be used for starting Direct3D (set up directX for using the 3D graphics acclerator) and creating g_gpu - which is our global variable for calling functions used on the graphics processing unit(gpu). I call it init_d3d_simple cuz we could make it more complicated by making a list of all available display and rendering options and let the user decide how the gpu should perform. We'll use a basic setup which is ideal for 2D games for now - I'm using 800x600 resolution as default - and A8R8G8B8 color format -- very common settings for a 2D game.
Init_d3d_simple will also set up a depth stencil buffer (z buffer) that is used to determine the final points visible on screen
end_d3d simply shuts it all down (clean up the memory and such)

void render();

(prototype for main graphics rendering function[in main.cpp] so we can call it from startup.cpp if we need to)

//for windows key disable:
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam );
//regular windows message handling procedure:
LRESULT CALLBACK default_window_proc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam);
void message_pump(void);
//mouse input stuff
void UpdateMouseCursor(LPPOINT xy);

#endif

LowLevelKeyboardProc (which we'll add to startup.cpp) will prevent the windows key from bothering us.
default_window_proc - our normal windows message handling procedure -- can respond to user input or to messages received by the operating system -- like for telling you the window is closing or a new joystick has been attached or a mouse button has been clicked or whatever
message_pump checks for messages, translates them, and dispatches them (which are then handled by the default_window_proc)
UpdateMouseCursor - I think we'll put the code for this prototype into main.cpp - we can capture the mouse position on the screen and store it in mouse.pos. This will be used in the title-screen for the game but could be used elsewhere if you wanted to.

STEP 9:

Go Solution Explorer - right click HeaderFiles>>Add>>New Item - HeaderFile(.h) - name it GameInput and add the following and don't forget to save...

#ifndef __GAMEINPUTHPP__
#define __GAMEINPUTHPP__

#include <math.h>
#include <windows.h>
#include <mmsystem.h>
#define _CRT_SECURE_NO_DEPRECATE
#ifndef _WIN32_DCOM
#define _WIN32_DCOM
#endif

#pragma warning( disable : 4996 ) // disable deprecated warning
#include <strsafe.h>
#pragma warning( default : 4996 )

We include useful headers for getting input and disable some deprecated warnings (warns you that certain stuff is outdated and wants you to transition to safer functions (ie: less possibility for problem for 64bit). I just prefer to use the old functions for now - no worries - we won't mess up.

The following definitions make getting keyboard input a little easier (keep in mind this is not actually using DInput for keyboard input - cuz it's just as fast this way anyhow)
KEY_IS_DOWN(KEY_J) for example would use GetAsyncKeyState function and mask the result to see if it is pressed or not -- if it is - the result is 1 (true) and 0 otherwise (false)
KEYPRESS(p) -- a very useful define which makes it so I can just say:
if KEYPRESS(SPACE) MakePlayerJump(); //which is easier than saying if (KEY_IS_DOWN(KEY_G)) MakePlayerJump();
The KEY_blablabla definitions after define the hexidecimal numbers that are associated with keyboard keys.

#define KEY_IS_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_IS_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
#define KEYPRESS(p) KEY_IS_DOWN(KEY_##p)
#define KEY_BACKSPACE 0x08
#define KEY_TAB 0x09
#define KEY_ENTER 0x0D
#define KEY_SHIFT 0x10
#define KEY_CONTROL 0x11
#define KEY_ALT 0x12
#define KEY_PAUSE 0x13
#define KEY_CAPS 0x14
#define KEY_ESCAPE 0x1B
#define KEY_SPACE 0x20
#define KEY_PAGEUP 0x21
#define KEY_PAGEDOWN 0x22
#define KEY_END 0x23
#define KEY_HOME 0x24
#define KEY_LEFT 0x25
#define KEY_UP 0x26
#define KEY_RIGHT 0x27
#define KEY_DOWN 0x28
#define KEY_PRINTSCREEN 0x2C
#define KEY_INSERT 0x2D
#define KEY_DELETE 0x2E
#define KEY_0 0x30
#define KEY_1 0x31
#define KEY_2 0x32
#define KEY_3 0x33
#define KEY_4 0x34
#define KEY_5 0x35
#define KEY_6 0x36
#define KEY_7 0x37
#define KEY_8 0x38
#define KEY_9 0x39
#define KEY_A 0x41
#define KEY_B 0x42
#define KEY_C 0x43
#define KEY_D 0x44
#define KEY_E 0x45
#define KEY_F 0x46
#define KEY_G 0x47
#define KEY_H 0x48
#define KEY_I 0x49
#define KEY_J 0x4A
#define KEY_K 0x4B
#define KEY_L 0x4C
#define KEY_M 0x4D
#define KEY_N 0x4E
#define KEY_O 0x4F
#define KEY_P 0x50
#define KEY_Q 0x51
#define KEY_R 0x52
#define KEY_S 0x53
#define KEY_T 0x54
#define KEY_U 0x55
#define KEY_V 0x56
#define KEY_W 0x57
#define KEY_X 0x58
#define KEY_Y 0x59
#define KEY_Z 0x5A
#define KEY_LWIN 0x5B
#define KEY_RWIN 0x5C
#define KEY_NUMPAD0 0x60
#define KEY_NUMPAD1 0x61
#define KEY_NUMPAD2     0x62
#define KEY_NUMDOWN    0x62
#define KEY_NUMPAD3 0x63
#define KEY_NUMPAD4    0x64
#define KEY_NUMLEFT     0x64
#define KEY_NUMPAD5 0x65
#define KEY_NUMPAD6     0x66
#define KEY_NUMRIGHT   0x66
#define KEY_NUMPAD7 0x67
#define KEY_NUMPAD8    0x68
#define KEY_NUMUP        0x68
#define KEY_NUMPAD9 0x69
#define KEY_MULTIPLY 0x6A
#define KEY_ADD 0x6B
#define KEY_UNDERSCORE 0x6C
#define KEY_SUBTRACT 0x6D
#define KEY_DECIMAL 0x6E
#define KEY_DIVIDE 0x6F
#define KEY_F1 0x70
#define KEY_F2 0x71
#define KEY_F3 0x72
#define KEY_F4 0x73
#define KEY_F5 0x74
#define KEY_F6 0x75
#define KEY_F7 0x76
#define KEY_F8 0x77
#define KEY_F9 0x78
#define KEY_F10 0x79
#define KEY_F11 0x7A
#define KEY_F12 0x7B
#define KEY_NUMLOCK 0x90
#define KEY_SCROLL 0x91
#define KEY_LSHIFT 0xA0
#define KEY_RSHIFT 0xA1
#define KEY_LCONTROL 0xA2
#define KEY_RCONTROL 0xA3
#define KEY_LALT 0xA4
#define KEY_RALT 0xA5
#define KEY_COLON 0xBA
#define KEY_PLUS 0xBB
#define KEY_COMMA 0xBC
#define KEY_MINUS 0xBD
#define KEY_PERIOD 0xBE
#define KEY_QUESTION 0xBF
#define KEY_SQUIGGLE 0xC0
#define KEY_LBRACKET 0xDB
#define KEY_OR 0xDC
#define KEY_RBRACKET 0xDD
#define KEY_QUOTE 0xDE
#define KEY_EQUALS VK_OEM_PLUS

#define PRESS_ESCAPE EscapeKey(g_escape_key_pressed)
// E S C A P E K E Y (make sure escape is unpressed before allowing new escape key capture)
bool EscapeKey(bool &pressed) {
   if (pressed) {
       if (KEY_IS_UP(KEY_ESCAPE)) pressed=false;
       return false;
   } else if (KEYPRESS(ESCAPE)) {
       pressed=true;
       return true;
    }
return false;
}

// S E T N U M L O C K (turns on NUMLOCK)
void SetNumLock(BOOL bState) {
    BYTE keyState[256];
    GetKeyboardState((LPBYTE)&keyState);
    if((bState&&!(keyState[VK_NUMLOCK]&1))||(!bState&&(keyState[VK_NUMLOCK]&1))){
        keybd_event(VK_NUMLOCK,0x45,KEYEVENTF_EXTENDEDKEY|0,0); // Simulate a key press
        keybd_event(VK_NUMLOCK,0x45,KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP,0); //sim release
    }
}

#endif

If the user hits the escape key for a fraction of a second - to the computer it looks like they are repeatdly pressing escape unless we make sure the button is unpressed before capturing a new escape keypress. This function is useful for checking escape keypressing cuz it prevents that problem.

Save and by now your solution explorer should have the following headers:

Solution Explorer

CLICK >> PAGE 2 << to continue to the next page in this tutorial.