Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Don't forget to read Tuesday's email newsletter for your chance to win a free copy of Construct 2!


This article is under review by the community - Current moderation totals:
Mark as peer reviewed: 1 votes (jbadams)
Still needs work: 0 votes


Like
11Likes
Dislike

Game Development with Win32 and DirectX 11 - Part 01: The Basic Framework UNDER REVIEW

By Josh Vega | Published Apr 26 2013 11:27 AM in Game Programming

Win32 DirectX 11 C++ D3D11

Introduction



Alright, now its time to get our hands dirty in some code. Before we move forward, please make sure you have read the first lesson in this series where we get all our prerequisites in order.

Let's Get Our Project Setup


So before we can actually start writing code, we'll need to get a Visual Studio project up and running. I'm expecting that by now, you already have Visual Studio open (if not please do so) and maybe you've already played around with it a bit. If you already understand how to setup a Win32 executable project in Visual Studio, please do so and then scroll down to the Project Settings sub-section.

Creating our Project


With Visual Studio open, click on File in the menubar. Then select New, Project.

Attached Image: File-New-Project.png

The New Project dialog should now open. Now this dialog can vary slightly, depending on the version of Visual Studio you are using (Express or Pro/Pre/Ult). In any case, you are going to want to find the Visual C++ tree, from the Install Templates sidebar. Under Visual C++, you are going to want to select Win32, Win32 Project. At the bottom of the dialog, select your solution name, and the directory in which you want to store it. Now, when you click Ok, the Win32 Application Wizard will appear.

In the wizard, click next to go ahead to the second page. Here is where we will decide what type of project we want to create. Since we want our game to run in a window, without the console showing up, we are going to select "Windows Application". Below that, you are going to want to select "Empty Project". Once all these settings are setup properly, you can go ahead and click Finish to generate your project.

Attached Image: Win32-Application-Wizard.PNG

Project Settings


Alright, now we have a working project. Before we go ahead and start coding, lets make some changes to the default settings for this project so that it better suits our needs.

Solution Organization

Before we get into the nitty-gritty settings, lets just make a small change to the organization of the Solution Explorer. You might notice that there are currently three file filters, Header Files, Resource Files, and Source Files (ignore External Dependencies for now). Different developers have different ways of organizing this project files. I've found that the most easy to use and organized way is to have each module of our game be located in a separate filter structure. So I took the project layout from this:

Attached Image: Solution-Explorer-Structure-Before.PNG

To:

Attached Image: Solution-Explorer-Structure-After.PNG

You can delete filters by clicking on the first one and then shift-clicking on the last one then pressing delete (a little dialog will popup, just click Ok). To add new filters, right click on the Project, select Add, then New Filter.

Attached Image: Project-Add-New-Filter.png

We really don't have to change any real settings just yet. We make some changes later on in this series though.

Time for Some Coding


Now that you have a properly setup project running, we can start coding. The way we are going to build our game is extremely simple. Now take note that this isn't your standard, single-file tutorial, we will be creating more and more files as the series progresses (that's why it's really important to use an IDE so you can keep everything organized). So with that in mind, let's begin.

Framework Design


Alright, so I lied. We aren't going to start coding just yet (but very soon). Before we get coding, I want to make sure you understand how we are going to build our game. Our game is going to consist of multiple modules:
  • Main: Not really a module, but it loads all the other modules and makes sure they are working properly.
  • Input: The input module will handle all keyboard and mouse (and eventually other devices) inputs.
  • Graphics: Probably the most interesting one for most of you, this will be a very lightweight wrapper around Direct3D 11.
  • Sound: Loads and plays sounds through XAudio2.
  • Game: The primary connection between the other modules and the Main module.
  • Scene: A simple scene-graph that is designed to be easily expandable.
Now, without further ado, let's get our hands dirty in some code!

Note:  In order to keep this article reasonably short, the complete source code will not be posted here. Rather, I will provide links to the source files which will be hosted on GitHub. Any source code written in here is to highlight a notable peice of code. Also, comments will not be placed in the embedded code snippets (GitHub contains fully-commented code).


Input


Ok, so first we'll start with the input module. For now, we aren't going to add too much meat to the modules. This is going to be one of the easiest modules to work with. Right now, we are only going to have 3 methods:

InputModule(void);

bool Initialize(void);
void Shutdown(void);

Header File Declaration
Source File Definition

Graphics


Next up is the graphics module. We are going to do the same thing as what we did with the input module.

GraphicsModule(void);

bool Initialize(void);
void Shutdown(void);

Header File Declaration
Source File Definition

Sound


Our sound module is going to follow the same pattern.

SoundModule(void);

bool Initialize(void);
void Shutdown(void);

Header File Declaration
Source File Definition

Scene


Finally, our scene-graph module will be the last to follow the same pattern.

SceneModule(void);
    
bool Initialize(void);
void Shutdown(void);

Header File Declaration
Source File Definition

Game


Alright, time for some real programming. First, let's include our different modules and the Win32 Api.

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#include "InputModule.h"
#include "GraphicsModule.h"
#include "SoundModule.h"
#include "SceneModule.h"

Now let's declare and define our methods, but let's do it a little differently this time.

GameModule(InputModule input, GraphicsModule graphics, SoundModule sound);
    
void Initialize(HINSTANCE instance);
void Shutdown(void);

void Show(bool show);

bool MainLoop(MSG *msg);

Header File Declaration
Source File Definition

Now, let's add a few private module pointers.

InputModule *inputPtr;
GraphicsModule *graphicsPtr;
SoundModule *soundPtr;
SceneModule *scenePtr;

HWND window;
WNDCLASSEX wndClass;

Header File Declaration

Lastly, let's make a couple global things:

static RECT windowSize = { 0, 0, 1280, 720 };

LRESULT CALLBACK WndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam);

Header File Declaration
Source File Definition

Main


Now comes our final piece of code, the WinMain function.

int WINAPI WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdLine, int cmdShow) {
    MSG msg;
    
    InputModule input = InputModule();
    GraphicsModule graphics = GraphicsModule();
    SoundModule sound = SoundModule();
    SceneModule scene = SceneModule();
    
    GameModule game = GameModule(input, graphics, sound, scene);
    
    game.Initialize();
    
    game.Show(true);
    
    if (!game.MainLoop(&msg)) {
        game.Show(false);
        game.Shutdown();
        
        return static_cast<int>(msg.wParam);
    }
    
    return 0;
}

Source File Definition

Compiling


You should now be able to compile your code. And have a result that is similar to the following:

Attached Image: Results.png

Project Source Code


If you would like to take a look at the complete source code for this lesson, please visit the official source code repository for this tutorial series, hosted on GitHub. I will also upload the source code as an attachment to this article, but it will not be updated with any bug-fixes or post-publication edits.

Lesson Tasks


Please perform the following actions to prepare yourself for the next tutorial:

  1. Change the code in GameModule::Initialize() to make one of the error message boxes show up (make sure to change it back once you are done to prepare for the next lesson).

Coming Up...


In the next tutorial, we'll begin adding some meat to our currently empty framework.

Post-Publication Changes


Please note that the source repository code has changed slightly after the initial publication of this article. Please see the associated commit for the changes from the intial code.





License


The GNU Lesser General Public License (LGPLv3)




Comments

I'm looking forward to this series after reading this, as my framework is logically ordered much the same(with the exception that module are each in their own static lib). I've made some decisions that I am now looking for alternatives to, and it will be nice to see the evolution of this framework as it proceeds.

Thanks for taking the time to make this, I especially like how you share all the files via a repository. There's just one thing, after the program has run I get this error: Debug Assertion Failed … _BLOCK_TYPE_IS_VALID(pHead->nBlockUse). I think this might be because in GameModule::Shutdown() you delete things that were created on the stack (in WinMain). When I remove those deletes I don't get the error anymore, so I'm fairly sure that's it.
Anyway, looking forward to the rest of the series!

In the GameModule constructor, you store pointers to the arguments of the constructor, instead of pointers to the objects created in WinMain. You should pass pointers to the constructor:

 

 

GameModule::GameModule(InputModule *input, GraphicsModule *graphics, SoundModule *sound, SceneModule* scene)
{
  this->inputPtr = input;
  this->graphicsPtr = graphics;
  this->soundPtr = sound;
  this->scenePtr = scene;
}
 

 

Then call it like:

 

 

GameModule game(&input, &graphics, &sound, &scene);
game.Initialize(instance);
 

Thanks for taking the time to make this, I especially like how you share all the files via a repository. There's just one thing, after the program has run I get this error: Debug Assertion Failed … _BLOCK_TYPE_IS_VALID(pHead->nBlockUse). I think this might be because in GameModule::Shutdown() you delete things that were created on the stack (in WinMain). When I remove those deletes I don't get the error anymore, so I'm fairly sure that's it.
Anyway, looking forward to the rest of the series!

 

Hmmm... That's interesting. I've compiled this program successfully with VS2010 and VS2012 with no problems. I do understand what you mean by deleting an object created outside the GameModule class, I'll look into it later when I get a chance.

 

 

In the GameModule constructor, you store pointers to the arguments of the constructor, instead of pointers to the objects created in WinMain. You should pass pointers to the constructor:

 

Wow! Nice catch. I'll go ahead a change the git code later when I get a chance.

The problem is that you are trying to delete objects in the GameModule::Shutdown() method even though you never created them using new.

The problem is that you are trying to delete objects in the GameModule::Shutdown() method even though you never created them using new.

 

Yeah that's what I was thinking the problem was. I will correct the code when I get a chance later tonight.

 

P.S. Sorry for any confusion or headaches this caused.

Alright, pushed a new, fixed version to the git repository (you can find the commit here). I'd just like to thank TomVeltmeijer, assainator, and Southee for letting me know about the error. If you still receive errors, I'm not sure what I can do for you (I test compiled the project again with Warning Level 4 just to make sure there was nothing I was missing).

What is the long term goal of this series?  I'm in the process of learning Win32 and DX11, so I was excited to see the headline of this article.  However, as I'm skimming through it, it looks to me like the format is geared more towards providing a code sample for people to look at rather than writing a comprehensive explanation of the concepts.  

 

The only explanations I can find in any level of detail are in the code's comments. While some may find that useful in its own right, I don't know if I would really call this an "article" as much as I'd call it a "code sample"

What is the long term goal of this series?  I'm in the process of learning Win32 and DX11, so I was excited to see the headline of this article.  However, as I'm skimming through it, it looks to me like the format is geared more towards providing a code sample for people to look at rather than writing a comprehensive explanation of the concepts.  

 

The only explanations I can find in any level of detail are in the code's comments. While some may find that useful in its own right, I don't know if I would really call this an "article" as much as I'd call it a "code sample"

 

Yes, I've realized that. At first, my use of providing all the actual "instruction" through code comments was an attempt to keep the articles reasonably short. I've realized my mistakes and in the future lessons, I will provide the code comments as supplementary text that will provide extra information beyond the requirements of this tutorial series. I'm sorry if this format has caused you any confusion.

 

As far as my long term goal, I actually have a few PMs on the subject and for this reason have postponed Part 02 until next week. This week I will be publishing Part 00.5 which will explain everything from what kind of game we are going to make to what game development concepts I will be covering throughout this series. As long as I don't have too much schoolwork, I should be able to get Part 00.5 published by Saturday (May 4th, 2013).

Just as a note on coding style you never type "this->" for member variables, most coding standards either use "m_" or "_" followed by the variable name for this to make them unique from parameters.
 
You should also not encode that something is a pointer in the name of a variable as someone might change their mind and change it to a reference or an object, the name will then however still imply it is a pointer when it is not. Hungarian notation is one of the worst coding practices you can do, using sensible names is far better, if something is a pointer you can tell by looking at the definition.
 
And in case of the pointers in this game module you can make them references as well if you want as you are initialising them in the constructor, this is what initialisation lists are for. References give you the same benefit as pointers in this case except that it makes it clear that the module doesn't own the referenced object.

As a side note this compiles fine in VS2012 as well, I can upload the converted project file to github if you want.

Just as a note on coding style you never type "this->" for member variables, most coding standards either use "m_" or "_" followed by the variable name for this to make them unique from parameters.

Yes, I was taught wrong and still have a habit of referencing them like that... :(

 

You should also not encode that something is a pointer in the name of a variable as someone might change their mind and change it to a reference or an object, the name will then however still imply it is a pointer when it is not. Hungarian notation is one of the worst coding practices you can do, using sensible names is far better, if something is a pointer you can tell by looking at the definition.

That is reminiscent of my work on the HPL Engine. They used the Hungarian style almost religiously.

 

And in case of the pointers in this game module you can make them references as well if you want as you are initialising them in the constructor, this is what initialisation lists are for. References give you the same benefit as pointers in this case except that it makes it clear that the module doesn't own the referenced object.

I see you're point, but I've had some really bad experiences with referencing everything in the constructor (again, from the HPL Engine). I guess it's worth-while to use it here since this is my own project.

 

As a side note this compiles fine in VS2012 as well, I can upload the converted project file to github if you want.

Why don't you fork my repo, push your changes to your fork, issue a pull request, and then I'll pull it into my repo. That way it'll be easier to manage in the future.


Just as a note on coding style you never type "this->" for member variables, most coding standards either use "m_" or "_" followed by the variable name for this to make them unique from parameters.

Yes, I was taught wrong and still have a habit of referencing them like that... sad.png


This is not wrong I always just find it looks silly and in certain cases you have to to resolve ambiguities.
 
Ill have a look at forking your repository and keeping it in line with VS2012 code.

Fork is created I can't push you the change though as the 2012 version changes the toolset the compiler is using in the vcxproj.

Fork is created I can't push you the change though as the 2012 version changes the toolset the compiler is using in the vcxproj.

Hmmm... I guess we can just run two repositories. Yours will be the VS12 one and mine will be the VS10 one. I'll make sure to push new changes early before the publication on the tutorial so that you can get a chance to pull them into your repo and test it on VS12. I mean, if this setup is alright with you...

copying from your Github commits there was a difference between GameModule.h and GameModule.cpp for the Initialize method and the MainLoop method. In the header file Initialize is return type bool, but in the source it has no return type, for the MainLoop it had bool in the header and int in the source, these were two easy fixes but surprising errors. 

copying from your Github commits there was a difference between GameModule.h and GameModule.cpp for the Initialize method and the MainLoop method. In the header file Initialize is return type bool, but in the source it has no return type, for the MainLoop it had bool in the header and int in the source, these were two easy fixes but surprising errors. 

 

I'm not sure what you mean? I just checked the code on github and both are properly typed. Besides, I wouldn't have pushed it to github if it didn't compile on VS2010 (on warning level 4).

Hi Josh,

Thank you for the great start there on the framework!

 

Is there any news where you will continue the series of the tutorial?

 

Thank you!


Note: Please offer only positive, constructive comments - we are looking to promote a positive atmosphere where collaboration is valued above all else.




PARTNERS