KillTux






3.89/5 (6投票s)
2001年3月11日

152345

3026
Space Donuts 3D for MFC。
描述
DirectX 8 SDK 自带的大部分示例都没有使用 MFC。如果我们想使用一个示例,并添加一些需要 MFC 的代码,该怎么办?
本文介绍了将“Space Donuts 3D”转换为 MFC 应用程序的步骤。
创建框架

启动 VC,从菜单中选择 File/New,然后选择 MFC Appwizard(exe)。给它一个名称(例如“BattleMachine”),然后按 OK 启动向导。 选择单文档作为应用程序类型,并取消选中文档/视图架构支持(图 1)。
单击“完成”。
添加甜甜圈
SDK 中的示例有很多全局函数和变量。我创建了一个名为 C3DEngine
的新类,并将大部分全局函数/变量复制为 C3DEngine
的成员。 然后,我在 theApp
的声明之后添加了 C3DEngine
的全局实例。
CBattleMachineApp theApp; C3DEngine g_3DEngine;
我还将以下两行添加到 BattleMachine.h 中,在 CBattleMachineApp
的定义之后
extern CBattleMachineApp theApp; extern C3DEngine g_3DEngine;
您可以通过添加文件 3DEngine.cpp 和 3DEngine.h,在您的应用程序中使用 Space Donuts 3D 引擎。 这些文件包含 space donuts 使用的任何其他类、结构和定义。
space donuts 3D 中有 2 个函数,我们无法将它们设为 C3DEngine
的成员。 一个是 ConfigureInputDevicesCB
,它是一个回调函数。 我们必须稍微修改它的代码,以引用 g_3DEngine 成员函数。
BOOL CALLBACK ConfigureInputDevicesCB( IUnknown* pUnknown, VOID* pUserData ) { //if( g_dwAppState != APPSTATE_ACTIVE ) if( g_3DEngine.g_dwAppState != APPSTATE_ACTIVE ) return TRUE; ...
另一个函数是 WindowProc
。 我将它的所有代码都移到了 CMainFrame::WindowProc
。 同样,对先前全局变量的引用必须更改为对 g_3DEngine
成员的引用。
框架的初始化和更改
要初始化 3D 引擎,您必须将 g_hWndMain
设置为有效的 HWND
,然后通过传递相同的 HWND 来调用 CreateGameObjects
。
设置窗口大小为 640x480 也是一个好主意,就像 space donuts 3D 一样。 我们通过使用 MainFrame 的 WHND 在 CMainFrame::OnCreate
中执行此操作。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { lpCreateStruct->cx=640; lpCreateStruct->cy=480; if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; // create a view to occupy the client area of the frame 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"); return -1; } SetWindowPos( NULL , 50,50, 640,480, SWP_NOOWNERZORDER | SWP_NOREPOSITION |SWP_NOZORDER ); g_3DEngine.g_hWndMain = GetSafeHwnd(); // Create the game objects (display objects, sounds, input devices, // menus, etc.) if( FAILED( g_3DEngine.CreateGameObjects( g_3DEngine.g_hWndMain ) ) ) { return FALSE; } return 0; }
然后,我们必须更改函数 CMainFrame::OnSetFocus
。 appwizard 生成的函数将焦点赋予 CChildView
窗口。 CMainFrame
应该保持焦点,因为我们需要处理来自 CMainFrame::WindowProc
的按键。
///////////////////////////////////////////////////////////////////////////// // CMainFrame message handlers void CMainFrame::OnSetFocus(CWnd* pOldWnd) { CFrameWnd::OnSetFocus(pOldWnd); // forward focus to the view window //m_wndView.SetFocus(); }
最后,我们将虚函数 OnIdle
添加到 CBattleMachineApp
类。 以下代码将渲染下一帧。
BOOL CBattleMachineApp::OnIdle(LONG lCount) { // Render a frame during idle time (no messages are waiting) if( g_3DEngine.g_bDisplayReady ) { g_3DEngine.FrameMove(); g_3DEngine.RenderFrame(); } return true; }
其他更改
我对原始的 space donuts 引擎进行了一些更改。
首先,我用 Tux 替换了甜甜圈、金字塔、立方体和球体的精灵。 毕竟,杀死甜甜圈不好玩!
其次,我通过更改函数 C3DEngine::HeightField
使地形更加平坦。 每个对象(飞船、子弹、甜甜圈)的高度都取决于该函数。
// Simple function to define "hilliness" for terrain 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; }
第三,我添加了飞船改变高度的能力。 通过使用鼠标滚轮,您可以抬起或降低飞船的鼻子,而不是更换飞船。 尝试飞过所有这些 Tux,并在不担心落在它们上面的情况下杀死它们。