<!-- Link to source file download -->
Download source files - 496 Kb
<!-- Link to demo file download -->
Download demo project - 583 Kb
<!-- Article image -->
<!-- Add the rest of your HTML here -->
Most of the samples that come with DirectX 8 SDK don't use MFC.
What if we want to take a sample and add some code that requires MFC?
This article describes the steps to convert the 'Space Donuts 3D'
into an MFC application.
Create the Framework
Start VC, Select File/New from the menu and select MFC Appwizard(exe).
Give a name (ex.'BattleMachine') and press OK to start the wizard.
Select Single document as the type of application and uncheck the
Document/View architecture support (Fig.1).
The Sample from the SDK have a lot of global functions & variables. I created
a new class named
C3DEngine and copy most of the global functions/variables as members of
C3DEngine. Then i added a global instance of
C3DEngine after the decleration of
I also added the following two lines in BattleMachine.h after the definition
extern CBattleMachineApp theApp;
extern C3DEngine g_3DEngine;
You can use the Space Donuts 3D engine in you application by adding the files
3DEngine.cpp and 3DEngine.h. Those files contain any other
classes, structs and definitions used by space donuts.
There are 2 functions from space donuts 3D that we can't make them members of
C3DEngine. One is
ConfigureInputDevicesCB which is a Callback function. We have to change it's code a little, to reference g_3DEngine member functions.
BOOL CALLBACK ConfigureInputDevicesCB( IUnknown* pUnknown, VOID* pUserData )
if( g_3DEngine.g_dwAppState != APPSTATE_ACTIVE )
The other function is
WindowProc. I moved all of it's code to the
CMainFrame::WindowProc. Once again, references to previously globals
has to change into references to members of
Initialisation and Changes to the framework
To initialise the 3D Engine you have to set
g_hWndMain to a valid
HWND and then call
CreateGameObjects by passing that same HWND.
Also a good idea is to set the window size to 640x480 as the space donuts 3D.
We do that in
CMainFrame::OnCreate by using the WHND of the MainFrame.
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
TRACE0("Failed to create view window\n");
SetWindowPos( NULL , 50,50, 640,480, SWP_NOOWNERZORDER | SWP_NOREPOSITION |SWP_NOZORDER );
g_3DEngine.g_hWndMain = GetSafeHwnd();
if( FAILED( g_3DEngine.CreateGameObjects( g_3DEngine.g_hWndMain ) ) )
Then we have to change the function
The function generated by appwizard gives focus to the
CMainFrame should keep the focus, because we need to handle
keypress from the
void CMainFrame::OnSetFocus(CWnd* pOldWnd)
Finally we add the virtual function
OnIdle to the
class. The following code will render the next frame.
BOOL CBattleMachineApp::OnIdle(LONG lCount)
if( g_3DEngine.g_bDisplayReady )
I made some changes to the original space donuts engine.
First, i replaced the sprites of donuts, pyramid, cube and sphere with Tux.
There's no fun killing donuts after all!
Second, I made the landscape more flat by changing the function
The height of every object (ship,bullets,donuts ) depence on that function.
inline FLOAT C3DEngine::HeightField( FLOAT x, FLOAT z )
return (cosf(x/2.0f+0.2f)*cosf(z/1.5f-0.2f)+1.0f)*0.1f - 2.0f;
Third, i added the ability to the ship to change altitude. By using
the mouse wheel, instead of changing ships, you can lift or drop the ship's nose.
Try to fly above all those Tuxs and kill them with no fear of dropping on them.