![]() |
Multimedia »
DirectX »
Games
Intermediate
A Simple and Powerful Game EngineBy S KellerThis article talks about a simple and powerful game engine to make game programming simpler |
C++, Windows, Visual Studio, DirectX, Dev
|
|
Advanced Search |
|
|
|
||||||||||||||||
This picture was taken from 3ds Max. This F-16 has 58,133 vertices that make 174,399 triangles.
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.
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.
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:
InitDirectX3D().CD3DFont class.////////////////////////////////////////////////////
//
////////////////////////////////////////////////////
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;
}
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:
Game_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;
}
This is what you get:

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:
Tools -> Options -> Directories (tab) -> (Include files) / (Library files) from the combo box-> add paths
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.
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.
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.
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!
| You must Sign In to use this message board. | |||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 23 Jul 2007 Editor: Genevieve Sovereign |
Copyright 2007 by S Keller Everything else Copyright © CodeProject, 1999-2009 Web15 | Advertise on the Code Project |