A Simple and Powerful Game Engine






4.45/5 (16 votes)
Jul 23, 2007
4 min read

92283

9124
This article talks about a simple and powerful game engine to make game programming simpler
This picture was taken from 3ds Max. This F-16 has 58,133 vertices that make 174,399 triangles.
- Introduction
- Using the code
- Initializing the game
- Game loop
- The results
- Additional futures
- How to compile
- SZM 3D model format
- How to make 3D models
- Resources and references
- Comments, suggestion or fixes
- History
Introduction
This article talks about a simple and powerful game engine that uses DirectX –3D, Input, Music and Show. With this engine you can render complex 3D models like terrains, cities, people, cars, etc., as well as play music and add 3D effects like velocity, position and direction to the music. You can play movies -- any movie that can be played by Windows Media Player -- and also use direct input for getting the keyboard, mouse and joystick input at full speed and in advanced usage. This article includes a plug-in for 3ds Max, i.e. Number 1 3D modeling for games, that exports 3ds Max scenes to the SZM format. The SZM model format is a very simple but powerful modeling format. Here is the documentation of the SZM model format.
Using the code
Every 3D game has an Init_Game()
, Game_Loop()
and a Game_Clean_Up()
function. In Init_Game()
, you initialize DirectX and load the needed models, music and videos. In the game loop, you check if there is any input from the keyboard or mouse and you process the input. You also calculate where each object should be. After all this, you render it to the screen. In the game clean-up, you do any cleaning up that is needed when quitting the game.
Initializing the game
First, create a window. Then, before entering the message loop, start the initializing like this:
//------------------------------------------------
::ShowWindow(g_GlobalData.hWnd,SW_SHOW);
::UpdateWindow(g_GlobalData.hWnd);
//------------------------------------------------
//
//Intialize Program.
//
if(!::Init_Game())
{
DestroyWindow(g_GlobalData.hWnd);
Return false;
}
//------------------------------------------------
Below is the Init_Game()
routine and this is what it does:
- Initialize some global variables, for example the zoom and the eye position, displaying the bounding boxes, etc.
- Initialize some variables of DirectX3D, i.e. to enable Z buffer, Global Ambient, 3DLighting, etc.
- Call
InitDirectX3D()
. - Create an object to be displayed.
- Play some video, only if you want to see a video now.
- After the video finishes playing, if you decided to play a video.
- You can play some music.
- Initialize direct input, i.e. mouse and keyboard input.
- Initialize a
CD3DFont
class. - You are done initializing!
////////////////////////////////////////////////////
//
////////////////////////////////////////////////////
BOOL Init_Game()
{
//Move Eye position back, so you can see the scene.
g_GlobalData.CameraEyeZ = -15000;
g_GlobalData.EyeX_Rotation=0;
g_GlobalData.EyeY_Rotation=0;
g_GlobalData.EyeZ_Rotation=0;
// How much to zoom (when using the mouse wheel).
g_GlobalData.m_dwMouseWheel = 10;
g_GlobalData.m_dwCameraMoveY = 10;
g_GlobalData.m_dwCameraMoveZ = 10;
g_GlobalData.bShowBoundingBoxs = TRUE;
g_GlobalData.bShowObjectBoundingBoxs = TRUE;
g_GlobalData.bShowWireFrame = FALSE;
g_GlobalData.dwInputSystemOldTime = 0;
g_GlobalData.bProcessInput = TRUE;
//---------------------------------
// Init the values that would be past to SetRenderState
g_DirectX3D.m_bEnableZBuffer = TRUE;
g_DirectX3D.m_dwGlobalAmbient = D3DCOLOR_ARGB(255,0,0,0);
g_DirectX3D.m_bEnableDirect3DLighting = TRUE;
g_DirectX3D.m_bEnableBackFacing = FALSE;
//---------------------------------
//Now Init DirectX 3d.
if(!g_DirectX3D.InitDirectX3D(g_GlobalData.hWnd))
return FALSE;
//---------------------------------
// g_DirectX3D.WritePC_CapabilitiesToFile("PC_Capabilities.txt");
//---------------------------------
//Create or Load an object to display for an example.
if(!::CreateAnObjectToDisplay())
return FALSE;
//---------------------------------
//g_DirectX3D.ShowFog();
//---------------------------------
//Clear Display
g_DirectX3D.Clear_Display(TRUE,TRUE,FALSE,DISPLAY_COLOR);
g_DirectX3D.Flip();
//---------------------------------
//->Show a Video.
//---------------------------------
g_DirectShow.Play(L"Movies\\Nsync - Bye Bye Bye.mpg",g_GlobalData.hWnd);
//->Turn on some Music.
//---------------------------------
if(!g_DirectSound.Init())
return FALSE;
if(!g_DirectSound.Load(L"Music\\Britney Spears – Crazy.mp3"))
return FALSE;
if(!g_DirectSound.CreateAudioPath(FALSE))
return FALSE;
if(!g_DirectSound.SetVolume(-1600))
return FALSE;
if(!g_DirectSound.PlayAudioPath(0))
return FALSE;
//---------------------------------
g_GlobalData.bInitWasDone = TRUE;
//---------------------------------
if(!g_Keyboard.Init())return FALSE;
if(!g_Mouse.Init())return FALSE;
//---------------------------------
//----------------------------
g_pFont = new CD3DFont( _T("Times New Roman"), 14, D3DFONT_BOLD );
g_pFont->InitDeviceObjects( g_DirectX3D.m_pD3dDevice );
g_pFont->RestoreDeviceObjects();
//----------------------------
return TRUE;
}
Game loop
In the message loop, call Prog_Loop()
like this:
//------------------------------------------------
while(1)
{
if( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
if( !::GetMessage( &msg, NULL, 0, 0 ) )
return msg.wParam;
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
else if(g_GlobalData.bInitWasDone)
{
::Game_Loop();
}
else
{
// make sure we go to sleep if we have nothing else to do
::WaitMessage();
}
}
//------------------------------------------------
This is what Game_Loop()
does:
- It checks if it is time to get input from the keyboard and mouse. Note that you can change it and make it check for input each time it enters
Game_Loop()
. - Sets transformation.
- Clears the display.
- Renders an object.
- Draws text.
- Flips the back buffer to the front buffer to display the new rendered scene.
- Rendering is done until the next loop.
////////////////////////////////////////////////////
//
////////////////////////////////////////////////////
BOOL Game_Loop()
{
//Get time.
g_GlobalData.dwCurrentTime = ::timeGetTime();
//--------------------------------------
//If passed a certain time check if there is any input.
if(g_GlobalData.dwCurrentTime > (g_GlobalData.dwInputSystemOldTime+10))
{
if(g_GlobalData.bProcessInput)
{
g_Keyboard.ProcessKey();
g_Mouse.ProcessMouse();
}
g_GlobalData.dwInputSystemOldTime = g_GlobalData.dwCurrentTime;
}
//--------------------------------------
//Set Transformations.
if(!g_DirectX3D.SetTransformations())
return FALSE;
//Clear Display.
g_DirectX3D.Clear_Display(TRUE,TRUE,FALSE,DISPLAY_COLOR);
//Render Object.
g_DirectX3D.RenderObject(&g_GlobalData.Object);
//--------------------------------------
//Draw Text.
g_pFont->DrawText( 380, 0, D3DCOLOR_ARGB(255,255,0,0), "My-Game!" );
//--------------------------------------
//Flip backbuffer to front buffer.
g_DirectX3D.Flip();
return TRUE;
}
The results
This is what you get:
Additional futures
- Fog
- Displaying text
- Lights
- Tilling textures
- Writing PC capabilities to a file
- Windowed or full screen
How to compile
You must have the DirectX 8 or 9 SDK. This is how to include the paths of the "include" and "lib" directories of the DX SDK:
Visual Studio 6
Tools -> Options -> Directories (tab) -> (Include files) / (Library files) from the combo box-> add paths
Visual Studio 8 (VS 2005)
Tools -> Options -> Projects and solutions (from the tree view) -> Visual C++ directories -> (Include files) / (Library files) -> add paths
It is best to make the new added paths the last in the list.
SZM 3D model format
At the beginning of the file, there is an SZM_File_header
structure. Right after it, there is a DWORD
that holds the number of MyMesh
structures. This is the header:
////////////////////////////////////////////////////
// Header
////////////////////////////////////////////////////
typedef struct _SZM_File_header
{
DWORD SZM_Sig;//'SZM '
DWORD version1;//'0004'
DWORD version2;//'0001'
}
SZM_File_header;
This is the DWORD
that holds the number of meshes in the file:
////////////////////////////////////////////////////
//
////////////////////////////////////////////////////
DWORD nMeshesInFile; // Number of meshes in the file.
This is how MyMesh
is declared:
////////////////////////////////////////////////////
// Now comes nMeshesInFile of MyMesh structures.
////////////////////////////////////////////////////
typedef struct _MyMesh
{
//--------------------------
DWORD nMeshName; // strlen(szMeshName)+1
char *szMeshName; // Mesh name.
DWORD nTextureFileName; // strlen(szTextureFileName)+1
char *szTextureFileName;// Texture File Name.
float UTilingData; // Texture n tiling at the U axis.
float VTilingData; // Texture n tiling at the V axis.
float UOffsetData; // Texture Offset at the U axis.
float VOffsetData; // Texture Offset at the V axis.
//--------------------------
D3DXMATRIX matTransformation;
//The transformation matrix that was applied to the mesh.
DWORD nVertex; // Number of Vertex of the mesh.
MyD3DVERTEX *pVertex; // Vertex Buffer.
//--------------------------
MyMaterial Material; // Mesh Material.
//--------------------------
// Is there a Bounding Box.
// The reason that some meshes don't have bounding boxes
// is that some meshes are part of a mesh that came before
// them, so that mesh bounding box also bounds on the following
// mesh (The reason that some mashed are divided to parts are
// because it can be meshes that different parts have a different
// material, so the mesh was divided to parts).
BOOL bHasBoundingBox;
Box BoundingBox; // Bounding Box.
Box3 MaxMinBox; // Mesh Max and Min points.
//--------------------------
DWORD nMesh; // Mesh-ID.
DWORD dwLevelInTree; // Level in the tree.
//--------------------------
}
MyMesh;
////////////////////////////////////////////////////
//
////////////////////////////////////////////////////
For more information, see SZM_Format.h and SZM_Loader.cpp.
How to make 3D models
The number 1 modeling program for games is 3ds Max, but 3ds Max is not free. If you want a free 3D modeling program, you can use Blender 3D. I don't really like to use Blender 3D, but maybe you can get used to it. For more information, you can read here.
Resources and references
- For more information on game engines, see here.
- For information on physics engines, see here.
- For information on game developing, see here.
Comments, suggestions or fixes
I would like to hear any comments, suggestions or fixes regarding this article. This would give me the motivation to write more articles. Enjoy your game!
History
- 23 July, 2007 -- Original version posted