• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
  • entries
    23
  • comments
    15
  • views
    29748

Entries in this blog

SpeedRun
The first release of the Breakout clone is finally here.

The Installer will install directx and the visual studio 2010 re-distributable.

If you would prefer to run the game through a zip file, you can download it from here. You will have to make sure that you have the visual studio 2010 re-distributables as well as the latest DirectX installed on your machine.

Try it out . Incase, you face any problems while installing or running the game, let me know and I will try to come up with a solution.

Looking forward to hearing your comments on the game icon_smile.gif

Crossposted here

[size=7]Screenshots


[sharedmedia=gallery:images:5149]
[sharedmedia=gallery:images:5150]
[sharedmedia=gallery:images:5152]
[sharedmedia=gallery:images:5151]

SpeedRun
For my next project, I have decided to make a clone of Asteroids as my second project. I would like to have a finished game by March 31st which gives me a month to finish the game. This time will include all the enhancements required in the engine so that the game is playable

[subheading]Why Asteroids[/subheading]

  1. Its a free form game with irregular goemetry which requires a more robust collision detection system.
  2. The ship has to move and accelerate in a way that resembles basic physics
  3. A High Score table makes sense since the scores can vary each game

Project updates soon
SpeedRun

PostMortem :MPong

I have decided to stop working on MPong. The reasons for this include

  1. I have been working on MPong for so long that it was tough to find motivation to continue working on it.
  2. Although I was continuously adding features to the engine, I was not building up my portfolio
  3. I want to test my engine with another game and see how much of the code is actually reusable. I am hoping most of it should be

[subheading]What Went Right[/subheading]

  1. Engine Components : Starting with Pong as my first game, made me concentrate on the engine part. I managed to create a fair amount of the modules I had initially aimed for. Most of the modules should be reusable for the next few games
  2. Setup: I managed to come up with a relatively painless way of setting up new projects
  3. Refactoring: I am quite happy with how the code base is at this point (all things considered). I think, The fact that I was continuously re factoring the code, will be beneficial.
  4. Commenting: I managed to comment a lot of my classes while programming.
  5. Using a Repository: Have a repository for my code, meant that I could revert any bugs that I introduced without having to waste too much time.

[subheading]What Went Wrong[/subheading]

  1. Missing Engine Components: I did not get a chance to work on the physics and networking modules.
  2. Switching to DirectX 11: In the middle of the project, I decided to switch to DirectX 11 from DirectX 9. Although this might be better going forward, I ended up fixing a lot of bugs that got introduced because of the difference in the way things are handled. Even now, some of the parts are not working correctly or are being done inefficiently by me.
  3. Engine Code was part of Project: I see a potential problem for my next project in that my engine setup and repository is closely tied to the Pong Project. I should have taken out the engine components and made it into a separate repository and solution, so that it was easily reusable
  4. Not Setting a Deadline: The fact that I did not have a deadline in place, meant that I took my own sweet time to make the game. This has resulted in Mpong being in development for a very long time, without me having to show anything for it
  5. Switching to an Obsolete Technology: I decided to use DirectSound or my SoundEngine.. It was only after completing that someone pointed out to me that I should have used XAudio instead

[subheading]Things I wish I had Implemented[/subheading]

  1. ?Physics and Networking modules
  2. Support for 2D game elements.
  3. High Score Table
  4. Better Graphics
  5. Restart Option
  6. Pause on Minimizing


cross-posted here
SpeedRun

We have sound

I have written a wrapper around DirectSound to take care of the sound.
I have also background music which was taken from http://www.nosoapradio.us/
I am currently working on a Options screen which allows to disable/enable the SFX and music channels and also set the respective volumes.
SpeedRun

New Release : Mpong

So I finally got around to making an installer using nsis.
The setup can be downloaded here

Edit:
The Archive can be downloaded here

ScreenShots
[sharedmedia=gallery:images:3091]
[sharedmedia=gallery:images:3092]
[sharedmedia=gallery:images:3093]
SpeedRun

Playable Prototype

I have finally got a playable prototype up and running.
The game supports both Single Player and Multiplayer Modes.

This also means that I have the following modules finished

  1. Game Logic

  2. Graphics

  3. Input

  4. UI

  5. AI

You can see the whole list here
[entry='2254511']What does making Pong take[/entry]

Next, I will be working on making a installer using nsis
SpeedRun
This snippet shows how to convert a point on screen to a corresponding point in the world. It borrows heavily from the concept of ray-tracing.

Let x and y be the point on the screen which we want to convert to the world space.
We need to create a ray which passes through the camera and the point(x, y) in worldSpace
This ray needs to satisfy the line equation [eqn]Pl = C + t * D [/eqn] (1)
where Pl = point along the line.
C = Point on the line. In this case the camera position
D = the Direction of the ray
t = some float

Now we need to get the direction of the ray.

First we transform the point to our View space coordinates. View space ranges from -1 to 1 on the x and y axis and 0 to 1 on the z axis with (0,0) being the center of the screen. We can set viewSpaceZ to 1 since the ray goes into the screen

We just reverse the following formula which is used to scale the the position in the world to fit the viewport size.
x = (ViewSpaceX + 1) * Viewport.Width * 0.5 + Viewport.TopLeftX
y = (1 - ViewSpaceY) * Viewport.Height * 0.5 + Viewport.TopLeftY
z = Viewport.MinDepth + ViewSpaceZ * (Viewport.MaxDepth - Viewport.MinDepth)

[spoiler]

viewSpaceX = ((2.0f * x) / screenWidth) - 1.0f;
viewSpaceY = -((2.0f * y) / screenHeight - 1.0f);
viewSpaceZ = 1.0f;

[/spoiler]

Next we adjust the points using the projection matrix to account for the aspect ratio of the viewport.
[spoiler]

viewSpaceX = viewSpaceX / projectionMatrix._11;
viewSpaceY = viewSpaceY/ projectionMatrix._22;
viewSpaceZ = viewSpaceY/ projectionMatrix._33;

[/spoiler]

To get our world matrix we just need to invert our view matrix.
Once we have our world matrix we can get the direction of our ray by transforming the viewspace point with the world matrix and then normalize the resultant vector.
[spoiler]

directionX = (viewSpaceX * worldMatrix._11) + (viewSpaceY * worldMatrix._21) + (viewSpaceZ * worldMatrix._31);
directionY = (viewSpaceX * worldMatrix._12) + (viewSpaceY * worldMatrix._22) + (viewSpaceZ * worldMatrix._32);
directionZ = (viewSpaceX * worldMatrix._13) + (viewSpaceY * worldMatrix._23) + (viewSpaceZ * worldMatrix._33);

// Normalize direction vector

[/spoiler]

At this stage, we have an infinite number of positions in the world which will fall on this ray(depending on the value of t)

To get the exact point in the world we need the intersection of this ray with the viewing plane.
The viewing plane be defined by the plane equation [eqn]Ax + By + Cz + k = 0[/eqn]
where N = (A, B, C) = the plane normal vector
k = Distance from the origin
Alternatively, the plane equation can be written as [eqn]dot(Pp,N) = k[/eqn] (2)
where Pp is the point on plane

To get the normal of our viewing plane in world space, we need the combination matrix of our view and projection matrix
[eqn]M = V.P. [/eqn]
Once we have our matrix M, the viewing plane normal is simply the normalized vector of (M._13, M._23, M._33)

When the plane and line intersect , [eqn]Pl = Pp[/eqn]
Substituting (1) in 2, we get
[eqn]dot(C + t *d, N) = k[/eqn]
Using distribution, we get
[eqn]dot(C + t *d, N) = dot(C,N) + t*dot(D,N) = k[/eqn]
Solving for t, we get
[eqn]t = (k - dot(C,N) ) / dot (D,N)[/eqn]

Once we have t, we can plug it back in equation (1) to get the point in our world.

This ends this mini tutorial of converting our screen coordinates to world coordinates
SpeedRun

Added Game Elements

I have added the basic Game elements which are

  • Walls
  • 2 Paddles
  • 1 Ball

    I have also added a UI to display the score.

    I have also written a model converter which takes an wavefront .obj file and converts it into a format which is easier to parse in my game engine. Currently the converter writes out the

    • the total number of vertices
    • vertex data (position and texture coordinate),
    • the total no of indices
    • the triangle data i.e the index data for each triangle

      It also creates a subset for each material which contains

      • the start index
      • the number of indices in this subset
      • the diffuse color
      • the texture file

        The in game Screen after clicking Single Player or Multiplayer

        [sharedmedia=gallery:images:3063]

        Next on the agenda is to get the paddles and ball moving and adding a collision checker
SpeedRun

Update

The last few weeks I have been moving my code from DirectX 9 to DirectX 11. Needless to say, it has been a time consuming process. I had to throw away a lot of my old code since DX11 changed the way things work. In the process, I ended up re-factoring a lot of my old and adding new elements.

Since I have got most of the base code in, I have started migrating the pong clone(MPong) from DirectX 9 to DirectX 11.

I have created the following menu screen.for the pong clone
[sharedmedia=gallery:images:3043]

Clicking on the singleplayer or multiplayer button just takes me to a blank screen for now. The Quit button is self explanatory.
Next I will be working on showing a table sprite when we go into the game and showing the paddles
SpeedRun

Timing and FPS

In this tutorial, we will learn how to create a timer to be used in our projects. We can use our timer for Creating a constant experience over multiple configurations, Calculating the FPS(Frames per second) etc.
The timer class will keep track of the Total Running Time, the time elapsed between 2 frames i.e between consecutive calls to Update and the FPS

[subheading]ITimer Interface : Timer.hxx[/subheading]
[spoiler]

namespace Utilities
{
class ITimer
{
public:
virtual ~ITimer(){}
UTILITIES_API virtual void VStartTimer() = 0;
UTILITIES_API virtual void VStopTimer() = 0;
UTILITIES_API virtual void VOnUpdate() = 0;
UTILITIES_API virtual bool VIsStopped() const = 0;
UTILITIES_API virtual float VGetFPS() const = 0;
UTILITIES_API virtual float VGetRunningTime() const = 0;
UTILITIES_API virtual TICK VGetRunningTicks() const = 0;
UTILITIES_API virtual float VGetDeltaTime() const = 0
UTILITIES_API static ITimer * CreateTimer();
};
}

[/spoiler]

[subheading]cTimer Class : Timer.h[/subheading]
The cTimer class handles the creation of the timer
[spoiler]

namespace Utilities
{
class cTimer
: public ITimer
, public Base::cNonCopyable
{
public:
static cTimer * Create();

private:
cTimer();
~cTimer();

void VStartTimer();
void VStopTimer();
void VOnUpdate();
bool VIsStopped() const;
float VGetFPS() const;
float VGetRunningTime() const;
float VGetDeltaTime() const;
TICK VGetRunningTicks() const;

private:
INT64 m_iTicksPerSecond;
INT64 m_iCurrentTime;
INT64 m_iLastUpdateTime;
INT64 m_iLastFPSUpdateTime;
INT64 m_iFPSUpdateInterval;
UINT m_iNumFrames;
float m_fRunningTime;
float m_fDeltaTime;
float m_fFPS;
bool m_bTimerStopped;
};
}

[/spoiler]

[subheading]Implementation : Timer.cpp[/subheading]
Constructor: In the constructor, we check how many times per second the system counter fires by making a call to QueryPerformanceFrequency. We also set the FPS update interval to half a second because if we updated the FPS every frame, it would change too fast for us to see.
[spoiler]

Utilities::cTimer::cTimer()
: m_iCurrentTime(0)
, m_iLastUpdateTime(0)
, m_iLastFPSUpdateTime(0)
, m_iNumFrames(0)
, m_fFPS(0.0f)
, m_fRunningTime(0.0f)
, m_fDeltaTime(0.0f)
, m_bTimerStopped(true)
{
if(!QueryPerformanceFrequency( (LARGE_INTEGER *)&m_iTicksPerSecond ))
{
// error
}

// update every half second
m_iFPSUpdateInterval = m_iTicksPerSecond >> 1;
}

[/spoiler]
Destructor:
[spoiler]

Utilities::cTimer::~cTimer()
{
}

[/spoiler]
Create: This function Create and Returns an object of this class.
[spoiler]

cTimer * Utilities::cTimer::Create()
{
return DEBUG_NEW cTimer();
}

[/spoiler]
VStartTimer: This function starts the timer if it has not already been started by getting the current value of the high-resolution performance counter.
[spoiler]

void Utilities::cTimer::VStartTimer()
{
if (m_bTimerStopped )
{
QueryPerformanceCounter( (LARGE_INTEGER *)&m_iLastUpdateTime );
m_bTimerStopped = false;
}
}

[/spoiler]
VStopTimer: This function stops the timer if it has not already been stopped and update the running time
[spoiler]

void Utilities::cTimer::VStopTimer()
{
if (!m_bTimerStopped )
{
INT64 iStopTime = 0;
QueryPerformanceCounter( (LARGE_INTEGER *)&iStopTime );

m_fRunningTime += (float)(iStopTime - m_iLastUpdateTime) / (float)m_iTicksPerSecond;
m_bTimerStopped = true;
}
}

[/spoiler]
VOnUpdate: This function Calculates the time elapsed since the last update call and updates the FPS and total running time.To calculate the FPS, we divide the frame counter by the time passed since the last time the FPS was calculated. Once the FPS is calculated, we reset the frame counter to 0.
[spoiler]

void Utilities::cTimer::VOnUpdate()
{
if (!m_bTimerStopped )
{
QueryPerformanceCounter( (LARGE_INTEGER *)&m_iCurrentTime );

m_fDeltaTime = (float)(m_iCurrentTime - m_iLastUpdateTime) / (float)m_iTicksPerSecond;
m_fRunningTime += m_fDeltaTime;

m_iNumFrames++;

if ( m_iCurrentTime - m_iLastFPSUpdateTime >= m_iFPSUpdateInterval )
{
// Calculate FPS
float fCurrentTime = (float)m_iCurrentTime / (float)m_iTicksPerSecond;
float fLastTime = (float)m_iLastFPSUpdateTime / (float)m_iTicksPerSecond;
m_fFPS = (float)m_iNumFrames / (fCurrentTime - fLastTime);

m_iLastFPSUpdateTime = m_iCurrentTime;
m_iNumFrames = 0;
}
m_iLastUpdateTime = m_iCurrentTime;
}
}

[/spoiler]
VIsStopped: Returns true if the timer is stopped
[spoiler]

bool cTimer::VIsStopped() const
{
return m_bTimerStopped;
}

[/spoiler]
VGetFPS: Returns the FPS
[spoiler]

float cTimer::VGetFPS() const
{
return m_fFPS;
}

[/spoiler]
VGetRunningTime: Returns the running time
[spoiler]

float cTimer::VGetRunningTime() const
{
return m_fRunningTime;
}

[/spoiler]
VGetRunningTicks: Returns the running ticks
[spoiler]

TICK cTimer::VGetRunningTicks() const
{
return (TICK)m_fRunningTime;
}

[/spoiler]
VGetDeltaTime: Returns the elapsed time between frames
[spoiler]

float cTimer::VGetDeltaTime() const
{
if (m_bTimerStopped)
{
return 0.0f ;
}
return m_fDeltaTime;
}

[/spoiler]
CreateTimer: Creates and returns a pointer to an object of this class
[spoiler]

ITimer * ITimer::CreateTimer()
{
return cTimer::Create();
}

[/spoiler]

[subheading]Using the timer[/subheading]
[spoiler]
Create the timer

pGameTimer = ITimer::CreateTimer();

Start The timer

pGameTimer->VStartTimer();

Update the timer each frame

pGameTimer->VOnUpdate();

Use the accessor functions
[/spoiler]
SpeedRun
[subheading]What does making Pong take?[/subheading]

  1. Game Logic
  2. Graphics
  3. Sound
  4. Input
  5. Physics
  6. UI
  7. AI
  8. Mutliplayer - P2p and/or Server Client and or shared input


Considering that pong is the simplest game that anyone can work on, the question arises why would I even want to make Pong. Even though the gameplay elements of Pong are simple, as you can see the underlying engine needs to have everything that a modern game has.

References :

  1. I had come across this article a while earlier. Its an interesting read and probably a reality check for people getting into games.
SpeedRun

Initializing DirectX

Now that we have created our window, we need to give it DirectX Capabilities, Again, since we will want to create only one instance of this class for each application we will create it as singleton. Even though on running the application we will just see a background color (TAN), we will have our DirectX device initialized and up for running. We will be able to Alt-Tab out of our full screen app or toggle between full screen and windowed mode

[subheading]Setting Up the Project[/subheading]
The DXSDK installation defines the DXSDK_DIR environment variable which can be used to include all the directX files into our project.
for all configurations
In the Project Properties -> C/C++ -> Additional Include Directories add $(DXSDK_DIR)\Include (apart from all the include files) (for all configurations)
In the Project Properties -> Linker -> Additional Library Directories add ..\..\bin\;"$(DXSDK_DIR)\Lib\x86"
Debug Mode
In the Project Properties -> Linker -> Input-> Additional Dependencies add d3dx9d.lib DxErr.lib d3d9.lib winmm.lib dinput8.lib dxguid.lib
Release Mode
In the Project Properties -> Linker -> Input-> Additional Dependencies add d3dx9.lib DxErr.lib d3d9.lib dinput8.lib dxguid.lib winmm.lib

[subheading]IDXBase Interface : DxBase.hxx[/subheading]
Since we dont need to expose all the functions to the rest of the world, we will just include a small subset in the interface. We will come to the purpose of each function in just a bit.
[spoiler]

namespace Graphics
{
class IDXBase
: public Base::cNonCopyable
{
public:
virtual ~IDXBase(){}
virtual void VOnInitialization(const HWND hWnd, const D3DCOLOR & bkColor, const bool bFullScreen, const int iWidth, const int iHeight) = 0;
virtual HRESULT VOnResetDevice() = 0;
virtual HRESULT VBeginRender() = 0;
virtual void VEndRender(const HRESULT hr) = 0;
virtual HRESULT VIsAvailable() const = 0;
virtual void VOnDestroy() = 0;
virtual LPDIRECT3DDEVICE9 VGetDevice() const = 0;
virtual void VToggleFullScreen() = 0;

GRAPHIC_API static IDXBase * GetInstance();
};
}

[/spoiler]

[subheading]cDxBase Class : DxBase.h[/subheading]
The cDxBase class handles the creation of the directX device
[spoiler]

namespace Graphics
{
class cDXBase
: public IDXBase
{
public:
static cDXBase * Create();
private:
cDXBase() ;
~cDXBase() ;
void VOnInitialization(const HWND hWnd, const D3DCOLOR& bkColor, const bool bFullScreen, const int iWidth, const int iHeight);
HRESULT VOnResetDevice() ;
HRESULT VBeginRender();
void VEndRender(const HRESULT hr);
LPDIRECT3DDEVICE9 VGetDevice() const;
HRESULT VIsAvailable() const;
void VOnDestroy();
void VToggleFullScreen();
void DirectxInit() ;
void CreateDirectxDevice() ;
void SetParameters();
void Cleanup() ;

private:
LPDIRECT3D9 m_pD3D ;
LPDIRECT3DDEVICE9 m_pd3dDevice ;
D3DCAPS9 m_Caps ;
D3DCOLOR m_BkColor ;
HWND m_Hwnd ;
D3DPRESENT_PARAMETERS m_d3dpp ;
int m_iWidth;
int m_iHeight ;
D3DDISPLAYMODE m_displayMode;
bool m_bFullScreen;
};
static cDXBase * s_pDXBase= NULL;
}

[/spoiler]

[subheading]Implementation : DxBase.cpp[/subheading]
Constructor
[spoiler]

cDXBase::cDXBase()
: m_pD3D(NULL)
, m_pd3dDevice(NULL)
, m_Hwnd(NULL)
, m_BkColor(BLACK)
, m_bFullScreen(false)
, m_iWidth(0)
, m_iHeight(0)
{
}

[/spoiler]
Destructor - Make sure the directX object and device are released
[spoiler]

cDXBase::~cDXBase()
{
Cleanup();
}

[/spoiler]
method Create - Creates an object of this class and returns it
[spoiler]

cDXBase* cDXBase::Create()
{
return(DEBUG_NEW cDXBase());
}

[/spoiler]
method VOnInitialization - This is the first function that needs to be called since it is responsible for creating the directX object and device
[spoiler]

void cDXBase::VOnInitialization( const HWND hWnd, const D3DCOLOR& bkColor, const bool bFullScreen, const int iWidth, const int iHeight)
{
m_Hwnd = hWnd;
m_BkColor = bkColor;
m_bFullScreen = bFullScreen;
m_iHeight = iHeight;
m_iWidth = iWidth;

// Initialize DirectX
DirectxInit() ;

// Fill out presentation parameters
SetParameters() ;

CreateDirectxDevice() ;
}

[/spoiler]
method VOnResetDevice - Resets the device
[spoiler]

HRESULT cDXBase::VOnResetDevice()
{
if (m_pd3dDevice)
{
HRESULT hr ;

hr = m_pd3dDevice->Reset(&m_d3dpp) ;
return hr ;
}
return 0;
}

[/spoiler]
method VBeginRender- This function clears the surface with the specified color and prepares it for rendering. This function must always be called before we render any geometry.
[spoiler]

HRESULT cDXBase::VBeginRender()
{
HRESULT hr;

// clear the frame with the specified color
m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, m_BkColor, 1.0f, 0) ;

hr = m_pd3dDevice->BeginScene() ;

return hr;
}

[/spoiler]
method VEndRender- This function displays what we just rendered to the screen .This function must always be called after we are done rendering
[spoiler]

void cDXBase::VEndRender( const HRESULT hr )
{
if(SUCCEEDED(hr))
{
m_pd3dDevice->EndScene() ;
}
// Present/Display the contents
m_pd3dDevice->Present(NULL, NULL, NULL, NULL) ;
}

[/spoiler]
method VGetDevice
[spoiler]

LPDIRECT3DDEVICE9 cDXBase::VGetDevice() const
{
return m_pd3dDevice;
}
[/spoiler]
method VIsAvailable - This function checks whether the device is available for rendering or not. We need to call this function before we begin rendering
[spoiler]

HRESULT cDXBase::VIsAvailable() const
{
return(m_pd3dDevice->TestCooperativeLevel()) ;
}
[/spoiler]
method VOnDestroy- Releases the DirectX object and deletes the singleton object
[spoiler]

void cDXBase::VOnDestroy()
{
Cleanup();
delete this;
s_pDXBase = NULL;
}
[/spoiler]
method VToggleFullScreen - Toggles between full screen and windowed mode
[spoiler]

void cDXBase::VToggleFullScreen()
{
m_bFullScreen = !m_bFullScreen;
SetParameters();
}
[/spoiler]
method DirectxInit- This function creates the Direct3D object. After creating the object, we get the system's current display mode by calling GetAdapterDisplayMode which will be used when we create a fullscreen device. Then we check what the video card is capable of by calling GetDeviceCaps.
[spoiler]

void cDXBase::DirectxInit()
{
//create the Direct3d Object
m_pD3D = Direct3DCreate9(D3D_SDK_VERSION) ;

if(m_pD3D == NULL)
{
\\ error
PostQuitMessage(0);
}

// get the display mode
m_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &m_displayMode );

// get the device caps
m_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &m_Caps) ;
}
[/spoiler]
method CreateDirectxDevice - This function check if the hardware supports transformation and lighting and whether it supports a pure device. In the end, we create the directX device based on the parameters that we have filled and the hardware capabilities.
[spoiler]

void cDXBase::CreateDirectxDevice()
{
int vp = 0 ; // the typeof vertex processing
if(m_Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
// hardware vertex processing is supported.
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING ;

// Check for pure device
if ( m_Caps.DevCaps & D3DDEVCAPS_PUREDEVICE )
{
vp |= D3DCREATE_PUREDEVICE;
}
}
else
{
// use software vertex processing.
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING ;
}

// Create the D3DDevice
if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, m_Hwnd, vp, &m_d3dpp, &m_pd3dDevice)))
{
\\ error
PostQuitMessage(0) ;
}
}
[/spoiler]
method SetParameters - This function fills out the D3DPRESENT_PARAMETERS structures depending on whether it is a full screen or windowed application. We also check which depth stencil format is supported by calling CheckDeviceFormat
[spoiler]

void cDXBase::SetParameters()
{
ZeroMemory(&m_d3dpp, sizeof(m_d3dpp)) ;

m_d3dpp.BackBufferCount = 1 ;
m_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE ;
m_d3dpp.MultiSampleQuality = 0 ;
m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD ;
m_d3dpp.hDeviceWindow = m_Hwnd ;
m_d3dpp.Flags = 0 ;
m_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE ;
m_d3dpp.EnableAutoDepthStencil = true ;
m_d3dpp.Windowed = !m_bFullScreen;

if(m_bFullScreen)
{
m_d3dpp.BackBufferWidth = m_iWidth;
m_d3dpp.BackBufferHeight = m_iHeight;
m_d3dpp.FullScreen_RefreshRateInHz = m_displayMode.RefreshRate;
m_d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; //pixel format
}
else
{
m_d3dpp.BackBufferWidth = 0;
m_d3dpp.BackBufferHeight = 0;
m_d3dpp.FullScreen_RefreshRateInHz = 0 ;
m_d3dpp.BackBufferFormat = m_displayMode.Format;
}

if (SUCCEEDED(m_pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8)))
{
m_d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
}
else if (SUCCEEDED(m_pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8)))
{
m_d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
}
else if (SUCCEEDED(m_pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16)))
{
m_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
}
else
{
// error
}
}

[/spoiler]
method Cleanup - This function releases the directx device and object. SafeRelease is a special macro which releases the object if it not released
[spoiler]

void cDXBase::Cleanup()
{
// release the Direct3d device
SAFE_RELEASE(m_pd3dDevice) ;

// release the Direct3d object
SAFE_RELEASE(m_pD3D) ;
}

[/spoiler]

[subheading]Running the code[/subheading]
The code needs to be added in the following functions
MainWindow.cpp
[spoiler]


void cMainWindow::OnWindowCreated()
//Bring the window into the foreground and activates the window
SetForegroundWindow(m_Hwnd);

//Set the keyboard focus
SetFocus(m_Hwnd);

// initialize DirectX
IDXBase::GetInstance()->VOnInitialization(m_Hwnd, TAN, m_bFullScreen, m_iFullScreenWidth, m_iFullScreenHeight);
}

void cMainWindow::OnWindowDestroyed()
{
// return to the default mode
ChangeDisplaySettings(NULL, 0);

// release the graphic object
IDXBase::GetInstance()->VOnDestroy();

ReleaseCapture() ;
PostQuitMessage(0) ;
}

void cMainWindow::VToggleFullScreen()
{
.. // previous code here

if (m_bFullScreen)
{
.. // previous code here
}
else
{
.. // previous code here
}

IDXBase::GetInstance()->VToggleFullScreen();
IDXBase::GetInstance()->VOnResetDevice();

if (!IsWindowVisible(m_Hwnd))
{
ShowWindow(m_Hwnd, SW_SHOW);
}
}

[/spoiler]

WinMain
[spoiler]

int WINAPI WinMain(const HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
.. // previous code
else
{
//No message to process?
// Then do your game stuff here
HRESULT hr = IDXBase::GetInstance()->VIsAvailable() ;

if(hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET)
{
if(hr == D3DERR_DEVICELOST)
{
Sleep(50);
}
else
{
if(hr == D3DERR_DEVICENOTRESET)
{
hr = IDXBase::GetInstance()->VOnResetDevice() ;
}
}
}
if(SUCCEEDED(hr))
{
hr = IDXBase::GetInstance()->VBeginRender();
}
if (SUCCEEDED(hr))
{
// render your stuff here
IDXBase::GetInstance()->VEndRender(hr);
}
}
..// destroy code
}

[/spoiler]
SpeedRun

Creating a Window

Before we create our game, we first need to know how to create a window. Thanks to OOP's the code just needs to be written just once. Since we will want to create only one instance of this class for each application we will create it as singleton.
[subheading]IMainWindow Interface : MainWindow.hxx[/subheading]
Since we dont need to expose all the functions to the rest of the world, we will just include a small subset in the interface. We will come to the purpose of each function in just a bit.
[spoiler]

namespace GameBase
{
class IMainWindow
: public Base::cNonCopyable
{
public:
virtual ~IMainWindow() {}
GAMEBASE_API virtual HWND VOnInitialization( const HINSTANCE & hInstance, const int & nCmdShow, const bool bFullScreen, const int iFullScreenWidth, const int iFullScreenHeight) = 0;
GAMEBASE_API virtual void VOnDestroy() = 0;
GAMEBASE_API virtual void VToggleFullScreen() = 0;
GAMEBASE_API static IMainWindow * GetInstance();
};
}

[/spoiler]
[subheading]cMainWindow Class : MainWindow.h[/subheading]
The cMainWindow class is the main class that handles the window creation and controls the message loop.
[spoiler]

namespace GameBase
{
class cMainWindow
: public IMainWindow
{
public:
HWND VOnInitialization(const HINSTANCE& hInstance, const int& nCmdShow, const bool bFullScreen, const int iFullScreenWidth, const int iFullScreenHeight);
void VOnDestroy();
void VToggleFullScreen();
static cMainWindow * Create();

private:
cMainWindow();
~cMainWindow();
static LRESULT CALLBACK StaticWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void RegisterWin() ;
void CreateMyWindow(const int& nCmdShow, const Base::cString& lpWindowTitle); LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
void OnWindowCreated();
void OnWindowDestroyed();
void SetDisplayResolution();

private:
const DWORD m_kdwFullScreenStyle;
const DWORD m_kdwWindowedStyle;
WINDOWPLACEMENT m_wp;
bool m_bFullScreen;
HWND m_Hwnd;
HINSTANCE m_hInstance;
int m_iFullScreenWidth;
int m_iFullScreenHeight;
};
}

[/spoiler]
[subheading]Implementation : MainWindow.cpp[/subheading]
Constructor
[spoiler]

cMainWindow::cMainWindow()
: m_bFullScreen(false)
, m_Hwnd(NULL)
, m_hInstance(NULL)
, m_iFullScreenHeight(0)
, m_iFullScreenWidth(0)
, m_pGame(NULL)
, m_kdwFullScreenStyle(WS_EX_TOPMOST | WS_POPUP | WS_VISIBLE)
, m_kdwWindowedStyle(WS_SYSMENU | WS_MINIMIZEBOX | WS_CAPTION)
{
ZeroMemory( &m_wp, sizeof( WINDOWPLACEMENT ) );
}

[/spoiler]
method VOnInitialization
[spoiler]

HWND cMainWindow::VOnInitialization( const HINSTANCE & hInstance, const int & nCmdShow, const bool bFullScreen, const int iFullScreenWidth, const int iFullScreenHeight )
{
m_hInstance = hInstance;
m_bFullScreen = bFullScreen;
m_iFullScreenWidth = iFullScreenWidth;
m_iFullScreenHeight = iFullScreenHeight;
if (m_iFullScreenWidth <= 0)
{
m_iFullScreenWidth = 1;
}
if (m_iFullScreenHeight <= 0)
{
m_iFullScreenHeight = 1;
}

RegisterWin();
SetDisplayResolution();
CreateMyWindow(nCmdShow, "MyWindow") ;
OnWindowCreated();
m_wp.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(m_Hwnd, &m_wp);
return m_Hwnd;
}

[/spoiler]
method VOnDestroy
[spoiler]

void cMainWindow::VOnDestroy()
{
DestroyWindow(m_Hwnd);

delete this;
s_pWindow = NULL;
}

[/spoiler]
method VToggleFullScreen - This method is used to toggle between windowed and full screen mode. We just need to set the appropriate style in the GWL_STYLE attribute of the window by calling SetWindowLongPtr.
[spoiler]

void cMainWindow::VToggleFullScreen()
{
m_bFullScreen = !m_bFullScreen;

SetDisplayResolution();

if (m_bFullScreen)
{
// Save Current location/size
GetWindowPlacement(m_Hwnd, &m_wp);

//Set style for Full Screen mode
SetWindowLongPtr(m_Hwnd, GWL_STYLE, m_kdwFullScreenStyle);

// hide the window
ShowWindow(m_Hwnd, SW_HIDE);
}
else
{
//Set style for Windowed mode
SetWindowLongPtr(m_Hwnd, GWL_STYLE, m_kdwWindowedStyle);

// reset the window location and size
SetWindowPlacement(m_Hwnd, &m_wp);

// allow other windows to come in front when we lose focus in windowed mode
SetWindowPos(m_Hwnd, HWND_NOTOPMOST, 0, 0,0, 0, SWP_NOMOVE | SWP_NOSIZE);
}

if (!IsWindowVisible(m_Hwnd))
{
ShowWindow(m_Hwnd, SW_SHOW);
}
}

[/spoiler]
method Create
[spoiler]

cMainWindow * cMainWindow::Create()
{
return(DEBUG_NEW cMainWindow());
}

[/spoiler]
method RegisterWin - Here, we need to define the window class by filling out a WNDCLASSEX structure. This structure tells Windows all the properties of the window that we want to create. The lpfnWndProc member is set to a function pointer that we will write later on. that has a specific function declaration:
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
When the program is compiled, another parameter is added to all non-static member functions, a this pointer, which changes the function declaration so it is incompatible with what is required for the lpfnWndProc member. Static functions on the other hand, do not receive this extra parameter, which is why we set the lpfnWndProc member to StaticWndProc. We register the window class for subsequent window class by calling RegisterClassEx
[spoiler]

void cMainWindow::RegisterWin()
{
WNDCLASSEX wc ;

wc.cbSize = sizeof(WNDCLASSEX) ;
wc.style = 0 ;
wc.lpfnWndProc = (WNDPROC)cMainWindow::StaticWndProc ;
wc.cbClsExtra = 0 ;
wc.cbWndExtra = 0 ;
wc.hInstance = m_hInstance ;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION) ;
wc.hCursor = LoadCursor(NULL, IDC_ARROW) ;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1) ;
wc.lpszMenuName = NULL ;
wc.lpszClassName = "Window" ;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION) ;
if(!RegisterClassEx(&wc))
{
//error
exit(0) ;
}
}

[/spoiler]
method CreateMyWindow - This function is responsible for creating the window. In the CreateWindow function, we can store any type of pointer we want in the last parameter(lpParam), such as a this pointer. Since our static window procedure does not have access to the "this" pointer, the "this" pointer which will be accessible during a WM_CREATE message, could be used to send messages meant for our application to a non-static window procedure, which would allow us to access the non-static data of our class. One of the attributes of all windows is a user-defined attribute, where we can store our this pointer in the user-defined attribute using the SetWindowLongPtr function with the GWLP_USERDATA offset flag
[spoiler]

void cMainWindow::CreateMyWindow( const int &nCmdShow, const cString & lpWindowTitle)
{
DWORD dwStyle;
if(m_bFullScreen)
{
dwStyle = m_kdwFullScreenStyle;
}
else
{
dwStyle = m_kdwWindowedStyle;
}

RECT windowRect;
windowRect.left = 0;
windowRect.top = 0;
windowRect.right = m_iFullScreenWidth;
windowRect.bottom = m_iFullScreenHeight;

//get the required size of the window rectangle, based on the desired size of the client rectangle
AdjustWindowRectEx(&windowRect, dwStyle, false, 0);

m_Hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
"Window",
lpWindowTitle.GetData(),
dwStyle,
CW_USEDEFAULT, 0,
windowRect.right - windowRect.left,
windowRect.bottom - windowRect.top,
NULL,
NULL,
m_hInstance,
this) ; // pass "this" so that staticwndproc can access the non static data

if(m_Hwnd == NULL)
{
//error
PostQuitMessage(0);
}

ShowWindow(m_Hwnd, nCmdShow) ;
}

[/spoiler]
method StaticWndProc - With the this pointer stored with our window, we can access it in all subsequent messages with the GetWindowLongPtr. Once the pointer is retreived, we can cast the pointer to a cMainWindow pointer and access all the non-static functions of the class, such as the non-static window procedure. Using this, we route all messages to their corresponding non-static window procedure.
[spoiler]

LRESULT CALLBACK cMainWindow::StaticWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
if ( msg == WM_CREATE )
{
// store the this pointer which is passed when we create the window in lparam
// lpCreateParams contains the value of the lpParam parameter specified in the function call.
SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG)((CREATESTRUCT *)lParam)->lpCreateParams );
}

// get the this pointer for this class using GWLP_USERDATA
cMainWindow *targetApp = (cMainWindow*)GetWindowLongPtr( hwnd, GWLP_USERDATA );

if ( targetApp )
{
// let our window handle the msg
return targetApp->WndProc( hwnd, msg, wParam, lParam );
}

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

[/spoiler]
method OnWindowCreated - This function will be called after the window is created. All our resources will be created here
[spoiler]

LRESULT CALLBACK cMainWindow::WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
PAINTSTRUCT ps ;
HDC hdc ;

switch(uMsg)
{
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
EndPaint (hwnd, &ps) ;
return 0 ;

case WM_CLOSE:
OnWindowDestroyed();
return 0 ;

case WM_DESTROY:
OnWindowDestroyed();
return 0 ;

case WM_ACTIVATE:
{
if (!HIWORD(wParam))
{
//active
}
else
{
//inactive
}
return 0;
}
//other messages
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam) ;
}
}

[/spoiler]
method WndProc - This function is used to process all our messages
[spoiler]

void cMainWindow::OnWindowCreated()
{
//Bring the window into the foreground and activates the window
SetForegroundWindow(m_Hwnd);
//Set the keyboard focus
SetFocus(m_Hwnd);
}

[/spoiler]
method OnWindowDestroyed - This function will be called after the window is destroyed. All our resources will be released here
[spoiler]

void cMainWindow::OnWindowDestroyed()
{
// return to the default mode
ChangeDisplaySettings(NULL, 0);

ReleaseCapture() ;
PostQuitMessage(0) ;
}

[/spoiler]
method SetDisplayResolution - This function sets the display settings of the monitor to the fullscreen width and height that has already been specified by filling the DEVMODE structure. ChangeDisplaySettings(NULL, 0) resets the display to the registry stored values
[spoiler]

void cMainWindow::SetDisplayResolution()
{
if (m_bFullScreen)
{
DEVMODE dmScreenSettings;
SecureZeroMemory(&dmScreenSettings, sizeof(dmScreenSettings));
if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dmScreenSettings))
{
//error
return;
}

// set the full screen height and width
dmScreenSettings.dmPelsHeight = m_iFullScreenHeight;
dmScreenSettings.dmPelsWidth = m_iFullScreenWidth;
dmScreenSettings.dmFields = (DM_PELSWIDTH | DM_PELSHEIGHT);

// Test if the requested graphics mode could be set.
if (ChangeDisplaySettings(&dmScreenSettings, CDS_TEST) == DISP_CHANGE_SUCCESSFUL)
{
// Set the requested graphics mode.
if(ChangeDisplaySettings(&dmScreenSettings, 0) == DISP_CHANGE_SUCCESSFUL)
return;
}
//error
}

// return to the default mode
ChangeDisplaySettings(NULL, 0);
return;
}

[/spoiler]
method GetInstance _ this function will create a cMainWindow object if it is not yet created and return a pointer to it
[spoiler]

IMainWindow * IMainWindow::GetInstance()
{
if(!s_pWindow)
s_pWindow = cMainWindow::Create();
return s_pWindow;
}

[/spoiler]
[subheading]Running the code[/subheading]
The WinMain function is the entry point of all Windows programs. Here we initialize the window and on quit destroy the window
[spoiler]

int WINAPI WinMain(const HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hWnd = IMainWindow::GetInstance()->VOnInitialization(hInstance, nCmdShow, false, 640,480);

MSG Msg;
PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE) ;
// run till completed
while (Msg.message!=WM_QUIT)
{
// is there a message to process?
if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
{
// dispatch the message
TranslateMessage(&Msg) ;
DispatchMessage(&Msg) ;
}
else
{
//No message to process?
// Then do your game stuff here
}
}

if (IMainWindow::GetInstance())
{
IMainWindow::GetInstance()-> VOnDestroy();
}
}

[/spoiler]
[subheading]Updates[/subheading]
Edit 14 Apr 2012 : Added a fix in VToggleFullScreen so that other windows can come in front when we lose focus in windowed mode.
SpeedRun

NonCopyable objects

Sometimes, you don't want to encounter a situation where something made a copy of the object. In C++, a copy of an object can be made in a number of situations. The most obvious is direct assignment. Less obvious, but equally valid, is a function call using pass-by-value.

Copying in C++ is handled in two ways

  • the copy assignment operator; and
  • the copy constructor

    Unfortunately, if the class definition does not explicitly declare a copy constructor or a a copy assignment operator, the compiler provides an implicit version which is a public member function.
    Now, if we want to make a class noncopyable, we can simply define its copy constructor and copy assignment operator as private members. But, it makes more sense to have a noncopyable base class. If a class derives from the noncopyable base class, it too will be noncopyable, since the copy of an object of a derived class must necessarily invoke the copy constructor or copy assignment operator of the corresponding base class.
    namespace Base
    {
    class cNonCopyable
    {
    protected:
    cNonCopyable(){}
    private:
    cNonCopyable(const cNonCopyable&);
    cNonCopyable operator =(const cNonCopyable&);
    }
    }


    By making the copy constructor or copy assignment operator private, we ensure that the derived class is noncoyable as well. By just providing the declaration and not implementing them, we ensure that the compiler does not provide its own versions and a linking error is generated if they are used anywhere in the program.
SpeedRun

Free Stuff

This title should get a lot of attention.tongue.gif

A list of free game libraries : Free Game Libraries
You are still here instead of going to the link . ohmy.gif
Even though the list hasnt been updated in a long time, its still the most complete list I have found. There are a ton of entries, and I would say it is pretty comprehensive. It would be nice, if it mentioned if the link/library was still active but you cant win them all.
This site breaks entries down into their general category ( 3D Graphics, 2D Graphics, Sound/Music, Networking, Video, Compression, Artificial Intelligence, Math/Physics, Scripting, etc. ), each entry contains a link to the library as well as the license it was released under
SpeedRun

Some Basic concepts

[subheading]DLL Basics[/subheading]
Since, we are going to be using dll's to have 1 single copy of our engine code, lets understand the basics of DLL's. For those of you, who are on the fence of whether to use a dll or not. Here are some of the advantages of using a dll as per MSDN

We will be using __declspec(dllexport) and__declspec(dllimport) to export and import functions, data and objects to and from a dll. We will mainly be using it to export/import functions or interface declarations and not member variables.

I prefer to have a header file which can encapsulate the above function calls. I will explain it with an example
#ifdef project_EXPORTS
#define project_API __declspec(dllexport)
#else
#define project_API __declspec(dllimport)
#endif

For the project from which we want to export functions, project_EXPORTS macro will be defined so that project_API automatically map to __declspec(dllexport). For all other projects project_API will map to __declspec(dllimport)

Now for whichever interface, we need to export all/the functions all we need to do is include the above header and add the following code
class project_API className
{
};

This takes care of exporting/importing all the functions, member variables in the class className.
SpeedRun

Memory Leak Woes

[subheading]Finding Memory Leaks[/subheading]
If you are not a big company, chances are you cannot afford the commercial programs to check for memory leaks in your program.. This tutorial will give you a free alternative which you can add to your projects.

The 1st thing that we need to do is to include . One thing to note is that crtdbg.h should be added after all the other header files

To make debugging easier, it would be nice if we could get the file and the line no which is causing the leak. Luckily, this can easily be done with some macro trickery
#ifdef _DEBUG
#define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_NEW new
#endif

The _DEBUG macro is defined only for release builds so by encasing the code in #ifdef/#endif quotes, we can ensure that we dont get sub-par code with Release Builds.
_NORMAL_BLOCK is the ordinary memory allocated by our program. Alternatively, we can use _CLIENT_BLOCK which is a special type of memory block (typically used by MFC programs) for objects that require a destructor.
__FILE__ and __LINE___ are predefined ANSI C macros which return The name of the current source file and the line number the current source file respectively.
Now all of our new operator calls three parameter new calls with the __FILE__ and __LINE__ automatically inserted by the pre-compiler.

We can override the new and delete functions to add our own custom tracking methods. We just need to make sure they atleast do what the old new/delete operator functions did.

The only thing remaining is to set the debug flags to enable memory leak detection. Make sure you call this function at the start of your program
[spoiler]void CheckForMemoryLeaks()
{
#ifdef _DEBUG
// Get Current flag
int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) ;

// Turn on leak-checking bit
flag |= (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF) ;

// Set flag to the new value
_CrtSetDbgFlag(flag) ;
#endif _DEBUG
[/spoiler]

The _CrtSetDbgFlag function allows the application to control how the debug heap manager tracks memory allocations by modifying the bit fields of the _crtDbgFlag flag.OR'ing the current _crtDbgFlag flag with _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF and setting it, the program automatically calls _CrtDumpMemoryLeaks when the program exits.

The _CrtDumpMemoryLeaks function determines whether a memory leak has occurred since the start of program execution. When a leak is found, the debug header information for all the objects in the heap is dumped in a user-readable form.

If you do not set _CRTDBG_LEAK_CHECK_DF, you will need to call _CrtDumpMemoryLeaks yourself.

[subheading]Additional Reading[/subheading]
You can read more about the different flags here

[subheading]Coming Up[/subheading]
In the next tutorial, we will look at creating a window
SpeedRun

[size="2"][font="Arial"][size="2"]Now that we have decided the basic directory structure and dependencies that each project will have, we will now set the project properties. I prefer to do this at the project level so that the properties are persistent and I don't have to set them every time I download the project. The steps are based on Visual 2008 Professional, but you can adapt them to a different IDE as well[/font]

[size="2"][font="Arial"][size="2"][subheading]Setup the Main Exe Project[/subheading][/font]

  • [font="Arial"][size="2"]Create an Win 32 Project and delete all the files except for stdafx.h, stdafx.cpp (I named the project as Main)[/font]
    • [font="Arial"][size="2"]Create a new folder called src and move the above files in there (I prefer all my source files in one main directory rolleyes.gif)
      [/font]
    • [font="Arial"][size="2"]In the property settings for the project perform the following steps[/font]
      • [font="Arial"][size="2"]For Both Release and Debug Modes[/font]
        • [font="Arial"][size="2"]In the tab C/C++ -> General -> Additional Include Directories add[/font]
          • [font="Arial"][size="2"]"$(SolutionDir)Common\src"[/font]
          • [font="Arial"][size="2"]"$(SolutionDir)Base\Includes"[/font]
          • [font="Arial"][size="2"]"$(SolutionDir)Utilities\Includes"[/font]
          • [font="Arial"][size="2"]"$(SolutionDir)GameBase\Includes"[/font]
          • [font="Arial"][size="2"]"$(SolutionDir)Game\src"[/font]
          • [font="Arial"][size="2"]For Debug Mode[/font]
              • [font="Arial"][size="2"]In the tab Debugging -> Working Directory add[/font]
                • [font="Arial"][size="2"]..\..\Debug\[/font]
                • [font="Arial"][size="2"]In the tab Linker -> General -> Output Directory add[/font]
                  • [font="Arial"][size="2"]..\..\Debug\[/font]
                  • [font="Arial"][size="2"]In the tab Linker -> General -> Output File add[/font]
                    • [font="Arial"][size="2"]$(OutDir)/$(ProjectName)_D.exe[/font]
                    • [font="Arial"][size="2"]In the tab Linker -> General -> Additional Library Directories add[/font]
                      • [font="Arial"][size="2"]..\..\Debug\[/font]
                      • [font="Arial"][size="2"]In the tab Linker -> Input -> Additional Dependencies add[/font]
                        • [font="Arial"][size="2"]Utilities_D.lib[/font]
                        • [font="Arial"][size="2"]Base_D.lib[/font]
                        • [font="Arial"][size="2"]Game_D.lib[/font]
                        • [font="Arial"][size="2"]For Release Mode[/font]
                          • [font="Arial"][size="2"]In the tab Debugging -> Working Directory add[/font]
                            • [font="Arial"][size="2"]..\..\bin\[/font]
                            • [font="Arial"][size="2"]In the tab Linker -> General -> Output Directory add[/font]
                              • [font="Arial"][size="2"]..\..\bin\[/font]
                              • [font="Arial"][size="2"]In the tab Linker -> General -> Output File add[/font]
                                • [font="Arial"][size="2"]$(OutDir)/$(ProjectName).exe[/font]
                                • [font="Arial"][size="2"]In the tab Linker -> General -> Additional Library Directories add[/font]
                                  • [font="Arial"][size="2"]..\..\bin\[/font]
                                  • [font="Arial"][size="2"]In the tab Linker -> Input -> Additional Dependencies add[/font]
                                    • [font="Arial"][size="2"]Utilities.lib[/font]
                                    • [font="Arial"][size="2"]Base.lib[/font]
                                    • [font="Arial"][size="2"]Game.lib[/font]

                                      [size="2"][font="Arial"][size="2"][subheading]Setting up the DLL's[/subheading][/font]

                                      [size="2"]

                                      [size="2"][font="Arial"][size="2"]I will explain how to setup one of the lib projects which links to an extern library. Properties for all the other projects can be set in the same way by looking at the dependencies from the previous tutorial[/font]

                                      [size="2"]

                                      • [font="Arial"][size="2"]Create an Win 32 Project but change the Application Type to DLL and delete all the files except for stdafx.h, stdafx.cpp (For tutorial purposes we will be setting up the Utilities project)[/font]
                                        • [font="Arial"][size="2"]Create a new folder called src and move the above files in there
                                          [/font]
                                        • [font="Arial"][size="2"]In the property settings for the project perform the following steps[/font]
                                          • [font="Arial"][size="2"]For Both Release and Debug Modes[/font]
                                            • [font="Arial"][size="2"]In the tab C/C++ -> General -> Additional Include Directories add[/font]
                                              • [font="Arial"][size="2"]"Includes"[/font]
                                              • [font="Arial"][size="2"]"..\Common\src"[/font]
                                              • [font="Arial"][size="2"]"..\Base\Includes"[/font]
                                              • [font="Arial"][size="2"]"..\..\extern\Include""[/font]
                                              • [font="Arial"][size="2"]For Debug Mode[/font]
                                                  • [font="Arial"][size="2"]In the tab Linker -> General -> Output Directory add[/font]
                                                    • [font="Arial"][size="2"]..\..\Debug\[/font]
                                                    • [font="Arial"][size="2"]In the tab Linker -> General -> Output File add[/font]
                                                      • [font="Arial"][size="2"]$(OutDir)/$(ProjectName)_D.dll[/font]
                                                      • [font="Arial"][size="2"]In the tab Linker -> General -> Additional Library Directories add[/font]
                                                        • [font="Arial"][size="2"]..\..\Debug\[/font]
                                                        • [font="Arial"][size="2"]..\..\extern\Lib\Zlib[/font]
                                                        • [font="Arial"][size="2"]..\..\extern\Lib\TinyXml[/font]
                                                        • [font="Arial"][size="2"]In the tab Linker -> Input -> Additional Dependencies add[/font]
                                                          • [font="Arial"][size="2"]Winmm.lib[/font]
                                                          • [font="Arial"][size="2"]tinyxmld.lib[/font]
                                                          • [font="Arial"][size="2"]Base_D.lib[/font]
                                                          • [font="Arial"][size="2"]zlibwapi.lib[/font]
                                                          • [font="Arial"][size="2"]For Release Mode[/font]
                                                            • [font="Arial"][size="2"]In the tab Linker -> General -> Output Directory add[/font]
                                                              • [font="Arial"][size="2"]..\..\bin\[/font]
                                                              • [font="Arial"][size="2"]In the tab Linker -> General -> Output File add[/font]
                                                                • [font="Arial"][size="2"]$(OutDir)/$(ProjectName).dll[/font]
                                                                • [font="Arial"][size="2"]In the tab Linker -> General -> Additional Library Directories add[/font]
                                                                  • [font="Arial"][size="2"]..\..\bin\[/font]
                                                                  • [font="Arial"][size="2"]..\..\extern\Lib\Zlib[/font]
                                                                  • [font="Arial"][size="2"]..\..\extern\Lib\TinyXml[/font]
                                                                  • [font="Arial"][size="2"]In the tab Linker -> Input -> Additional Dependencies add[/font]
                                                                    • [font="Arial"][size="2"]tinyxml.lib[/font]
                                                                    • [font="Arial"][size="2"]Winmm.lib[/font]
                                                                    • [font="Arial"][size="2"]Base.lib[/font]
                                                                    • [font="Arial"][size="2"]zlibwapi.lib[/font]

                                                                      [size="2"][font="Arial"][size="2"]Notes:[/font]

                                                                      [size="2"]

                                                                      1. [font="Arial"][size="2"]To point to the directx dir we can use the visual studio macro $(DXSDK_DIR)\Include[/font]
                                                                      2. [font="Arial"][size="2"]I use the suffix _D to distinguish between debug and release builds[/font]
                                                                      3. [font="Arial"][size="2"]For the most part, only the Include folder should be added in the additional include directories. Exceptions Being GameBase and Game[/font]

                                                                      [font="Arial"][size="2"][subheading]Final Thoughts[/subheading][/font]

                                                                      [font="Arial"][size="2"]This finishes the initial setup. Since I am not sure, how much detail I should get into of why I setup my projects this way, I will be happy to answer any questions in the comments.[/font]

                                                                      [size="2"][font="Arial"][size="2"]The next tutorial will deal with the common includes, macros and how to make the debugger check for Memory Leaks[/font]cool.gif

SpeedRun
In this post I am going to cover the third party libraries, project breakup, and current directory structure that I follow. Even though its not perfect, its served me well so far

[subheading]Third Party Tools[/subheading]

  1. [font=Arial]FMod - Sound[/font]
  2. [font=Arial]TinyXML - XML[/font]
  3. [font=Arial]Zlib - zip[/font]

[subheading]Projects in the Solution[/subheading]

  • Common

    • Common includes, macros etc that should be included in every project
    • Dependencies - None
    • Project Includes - None
    • Additional Includes - None
    • Third Party Libraries - None
    • Base

      • common datastructures/classes such as wrappers for string
      • Dependencies - None
      • Project Includes - Common
      • Additional Includes - None
      • Third Party Libraries - None
      • Utilities

        • All Utility Functions such as Logger
        • Dependencies - Base
        • Project Includes - Common, Base
        • Additional Includes - Third Party includes (see extern below)
        • Additional Libraries - [font=Arial]Winmm.lib tinyxml.lib zlibwapi.lib[/font]
        • AI

          • AI related Functionality
          • Dependencies - Base, Utilities
          • Project Includes - Common, Base
          • Additional Includes - None
          • Additional Libraries - [font=Arial]None[/font]
          • GraphicsEngine

            • All Graphic related stuff
            • Dependencies - Base, Utilities
            • Project Includes - Common, Base, Utilities
            • Additional Includes - DirectX Includes
            • Additional Libraries - [font=Arial]d3dx9.lib DxErr.lib d3d9.lib winmm.lib dinput8.lib dxguid.lib[/font]
            • Sound

              • Wrappers for playing sound ([color=#ff0000]might move to Graphics Engine later[/color])
              • Dependencies - Base, Utilities
              • Includes - Common, Base, Utilities
              • Additional Includes - Third Party includes (see extern below)
              • Additional Libraries - [font=Arial]fmodex_vc.lib[/font]
              • GameBase

                • Functionality that needs to be setup every game
                • Dependencies - Base, Utilities, GraphicsEngine
                • Includes - Common, Base, Utilities, GraphicsEngine
                • Additional Includes - DirectX Includes
                • Additional Libraries - [font=Arial]None[/font]
                • Game

                  • GamePlay Logic (This project will be swapped for different games)
                  • Dependencies - Base, Utilities, GraphicsEngine, GameBase, Sound
                  • Includes - Common, Base, Utilities, GraphicsEngine, GameBase, Sound, AI
                  • Additional Includes - DirectX includes
                  • Additional Libraries - [font=Arial]None[/font]
                  • Main

                    • The exe file
                    • Dependencies - Base, Utilities, Game
                    • Project Includes - Common, Base, Utilities, Gamebase, Game
                    • Additional Includes - None
                    • Additional Libraries - [font=Arial]None[/font]


                      [font=Arial][subheading]Directory Structure[/subheading][/font]
                      [font=Arial]For each Project I mantain 2 folders[/font]

                      • [font=Arial]Include[/font]

                        • [font=Arial]This folder contains all the interfaces for the respective project. This folder will be included in the all projects that are dependent on it. This way, the underlying implementations need not be released. It also reduces the compile time, if i change the implementation[/font]
                        • [font=Arial]Src[/font]

                          • [font=Arial]This folder contains all files for the actual implementation. Most of the classes would be inheriting from one of the interfaces in the Include folder[/font]



                            [font=Arial][subheading]Final Thoughts[/subheading][/font][font=Arial]Now that we have the basic directory structure mapped out, the next tutorial will deal with actually setting up the project for the Visual 2008 environment.[/font]

                            [font=Arial]Till Next Time[/font]smile.gif
SpeedRun

The Beginning

Welcome to my blog.
Over a period of time, I hope to fill this space with the status of my projects as well as tutorials for some basic stuff.cool.gif

Although, I have been posting at http://speedrunsdev.blogspot.com previously, I am creating this journal for a number of reasons:
  • Post my ideas and progress, open for other people to critique and offer suggestions.
  • Subsequently, this should keep me motivated so that I don't leave my projects midway, once the initial enthusiasm gets over :-)
    I am currently working on a basic GameEngine that can be reused easily. For testing, I have developed a basic clone of Pong. Needless to say a lot still needs to be done.

    The code and projects will still be available at http://speedrunsdev.blogspot.com

    The first few tutorials will be cross posted from my previous blog with minor updates to how the library looks right now
    I will be posting the few small projects I have worked on soon.

    Tune in later for an update smile.gif
Sign in to follow this  
Followers 0