65.9K
CodeProject 正在变化。 阅读更多。
Home

KillTux

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.89/5 (6投票s)

2001年3月11日

viewsIcon

152345

downloadIcon

3026

Space Donuts 3D for MFC。

  • 下载源文件 - 496 Kb
  • 下载演示项目 - 583 Kb
  • Sample Image - KillTux1.gif

    描述

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

    创建框架

    figure 1

    启动 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.cpp3DEngine.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,并在不担心落在它们上面的情况下杀死它们。

    © . All rights reserved.