|
|

楼主 |
发表于 2005-8-4 07:21:00
|
显示全部楼层
Re: 找扁的游戏制作教程(四)
- // 包含km3d引擎的头文件
- #include "AppInclude.h"
- #include "MainApp.h"
- // 包含资源文件[例如应用程序图标,已经程序的版本信息]
- #include "resource.h"
- // 定义的一些全局变量的东西,我都塞到这个结构里面了
- #include "GlobalFunction.h"
- // 程序开始的时候希望显示一段Splash界面
- #include "SplashWindow.h"
- // 包含鼠标控制,打算使用自己而不是系统的鼠标样子
- #include "GameCursor.h"
- // 游戏主菜单界面[我把游戏状态分为主选菜单状态,游戏Loading状态和游戏状态]
- #include "MainMenuWnd.h"
- // 以下的应用程序主窗口和句柄我总是很多时候要用到的
- MainApp * g_pApp = NULL;
- HINSTANCE g_hInst = NULL;
- // 得到程序版本号
- int GetAppVersion(const char *pFileName)
- {
- // 实现具体参见源代码
- // 从该exe文件中得到该程序的版本信息,制作信息等等
- }
- // 装载Config设置
- BOOL LoadAppConfig()
- {
- // 装载配置文件,实现参见源代码
- // 从xml配置文件中获取,例如渲染模式OGL/D3D
- // 或者全屏幕还是窗口运行
- // 是否显示fps
- // 以及程序窗口分辨率的大小等等
- KM3D_XMLHANDLE* pXmlHandle = KM3D_XmlHandle_Create("config.xml");
- }
- INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR /* lParam */, INT /* nCmdShow */)
- {
- MainApp d3dApp;
- g_pApp = &d3dApp;
- g_hInst = hInst;
- if( FAILED(CoInitialize(NULL)))return FALSE;
- // 初始化随机的种子[游戏总是会出现随机的地方,种子先]
- srand( (unsigned)time( NULL ) );
- // 初始化声音
- KM3D_InitSound();
- // 初始化游戏全局脚本
- g_Globle.pLuaWrap = new LuaWrap;
- if(g_Globle.pLuaWrap == NULL
- || g_Globle.pLuaWrap->LoadFile("Data\\GlobalFunc.lua") == FALSE )
- {
- return FALSE;
- }
- // 装载应用程序配置
- if(LoadAppConfig() == FALSE)return FALSE;
- // 获得程序版本号
- d3dApp.m_nAppVersion = GetAppVersion("QYClient.exe");
- if(d3dApp.m_nAppVersion == 0)d3dApp.m_nAppVersion = 3925;
- sprintf(d3dApp.m_szAppVersion, "Qi Yuan Version %d", d3dApp.m_nAppVersion);
- g_Globle.nAppVersion = d3dApp.m_nAppVersion;
- // 设置打算使用的应用程序标题
- d3dApp.SetWindowsTitel(d3dApp.m_szAppVersion);
- // 显示一段Splash图片界面,在显示游戏窗口前
- SplashWindow::S_ShowSplashWindow();
- #ifdef _DEBUG
- // 如果是Debug模式,强制使用窗口模式运行
- g_pApp->SetFullScreen(FALSE);
- #endif
- // 建立游戏窗口,并向km3d引擎注册全局lua脚本,以便km3d引擎能够使用这些脚本
- if( FAILED( d3dApp.CreateScreen( g_hInst,
- "Qi Yuan II Class",
- TRUE,
- LoadIcon( hInst, MAKEINTRESOURCE(IDI_QIYUCLIENT) ),
- (PFCALLREGAPPLUAFUNCTION)RegisterGlobalLuaFunc) ) )
- {
- return FALSE;
- }
- // 设置游戏fps定帧,如果不需要,修改APP_FRAME_LIMIT定义为0
- d3dApp.SetLimitFps(APP_FRAME_LIMIT);
- return d3dApp.Run();
- }
- MainApp::MainApp(void)
- {
- //...
- //...
- // 设置抓取屏幕开关关闭
- m_bScreenShotFlag = FALSE;
- }
- MainApp::~MainApp(void)
- {
- KM3D_SAFE_DELETE_ARRAY(m_pEnglistTextureData);
- KM3D_FontHandle_Close(m_pSytemFont);
- KM3D_FontHandle_Close(m_pDefaultFont);
- m_pDefaultFont = NULL;
- }
- HRESULT MainApp::ConfirmDevice( D3DCAPS9* pCaps, uint32 dwBehavior,
- D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat )
- {
- // d3d设备确认
- // d3d模式下需要或者不需要,opengl模式下直接返回好了
- }
- HRESULT MainApp::OneTimeSceneInit()
- {
- // 注意这里不要初始化和设备相关的
- // 例如读取设置其他游戏数据信息等等
- // 好比读取某些数据配置文件等.网络初始化也可以放在这里,但是不建议放在这里
- }
- HRESULT MainApp::InitDeviceObjects()
- {
- // 初始化和设备相关的东西,例如贴图,模型等
- HRESULT hr;
-
- // 如果用km3d引擎,这个需要放在本函数的开始,因为km3d它自己要初始化一些东西
- if(FAILED (hr = KM3D_InitDeviceObjects() ) )
- {
- return hr;
- }
- // 我们开始读取一张字体的贴图
- // 该贴图必须放在data目录下.程序会先找相应的目录下的文件,
- // 如果找不到则到Textures的包文件中去读取
- long nWidth, nHeight;
- if( KM3D_Texture_LoadToBuffer("Textures\\Font\\DefaultFont.blp",
- &m_pEnglistTextureData, nWidth, nHeight) == FALSE )
- return E_FAIL;
- // 初始化一个非系统安装的字体,也许游戏中我们想要自己定义一个字体
- char szFontName[128];
- char szFontPathName[MAX_PATH];
- strncpy(szFontName,
- g_Globle.pLuaWrap->GetGlobal<const char*>("DEFALUT_FONT_FILENAME"), 128);
- _snprintf(szFontPathName, MAX_PATH, "Fonts\\%s", szFontName);
- DeleteFile("QIYUN_D.FOT");
- CreateScalableFontResource(1, "QIYUN_D.FOT", szFontName, "Fonts");
- if( AddFontResource(szFontPathName) == 0)return E_FAIL;
- m_pDefaultFont = KM3D_FontHandle_Create(
- g_Globle.pLuaWrap->GetGlobal<const char*>("DEFALUT_FONT_FACENAME"),
- m_pEnglistTextureData);
- if(m_pDefaultFont == NULL)return E_FAIL;
- if(FAILED ( hr = KM3D_Font_InitDevice(m_pDefaultFont) ) )
- {
- return hr;
- }
- // 添加一种系统字体[注意请自行判断系统中是否有该字体]
- m_pSytemFont = KM3D_FontHandle_Create(
- g_Globle.pLuaWrap->GetGlobal<const char*>("SYSTEM_FONT_FACENAME"),
- m_pEnglistTextureData);
- if(m_pSytemFont == NULL)return E_FAIL;
- if(FAILED ( hr = KM3D_Font_InitDevice(m_pSytemFont) ) )
- {
- return hr;
- }
- // 装载游戏的鼠标
- // 为什么用3d模型文件来做鼠标呢?参照readme说明,我这里极力推荐
- g_pGameCursor = new GameCursor;
- if( g_pGameCursor == NULL
- || !g_pGameCursor->Load("Interface\\Cursor\\Cursor.mdx")
- || FAILED(g_pGameCursor->InitDeviceObjects() ) )
- {
- return E_FAIL;
- }
- g_pMainMenuWnd = new MainMenuWnd;
- if(g_pMainMenuWnd==NULL
- || g_pMainMenuWnd->Init() == FALSE
- || FAILED(g_pMainMenuWnd->InitDeviceObjects()) )
- {
- return E_FAIL;
- }
- // 将游戏的界面状态设置为主选菜单窗口
- g_Globle.nGameStata = S_MAIN_MENU_WND;
- // 初始化所有的模型和贴图相关的东西
- // 为什么需要这样做了, 这里是对调入模型和贴图进行一个规整.
- // 也就是统个计,排个序什么的
- // 当然因为km3d引擎也都提供d3d和ogl接口,所以如果你打算自己管理,也没有问题
- // 这里的管理只是针对偷懒的调入
- KM3D_MDX_InitDeviceObject_All();
- KM3D_Texture_InitDeviceObject_All();
- }
- HRESULT MainApp::RestoreDeviceObjects()
- {
- // 恢复设备内容, 除非你自己管理的设备内容,否则引擎已经自己会恢复的
- }
- HRESULT MainApp::InvalidateDeviceObjects()
- {
- // 使设备无效, 除非你自己管理的设备内容,否则引擎已经自己会恢复的
- }
- HRESULT MainApp::DeleteDeviceObjects()
- {
- // 退出游戏前,清理一下设备里面的内容
- // ..
- // ..
- // 让引擎自己清理一下引擎内部自己创建的
- KM3D_MDX_DeleteDeviceObject_All();
- KM3D_Texture_DeleteDeviceObject_All();
- }
- // 关闭程序前,你要做的一些扫尾工作
- HRESULT MainApp::FinalCleanup()
- {
- // 参见代码实现
- }
- HRESULT MainApp::FrameMove()
- {
- // 这里抓图
- if(m_bScreenShotFlag)
- {
- m_bScreenShotFlag = FALSE;
- KM3D_ScreenShot();
- }
- // 计算和渲染是分开的,意思就是算好了一起画,而不要一边计算一边画,那时傻子做的事
- // 参见代码实现
- }
- // 描述: 渲染部分
- HRESULT MainApp::Render()
- {
- HRESULT hr;
- // 清理一下屏幕
- if(FAILED (hr = KM3D_3D_ClearScreen(0L, NULL,
- D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0, 1.0f, 0L) ) )return hr;
- // 通知引擎说,我打算开始要画东西了,让其准备一下.意思就是说我要尿尿了,你端个盆来
- if(FAILED (hr = KM3D_3D_BeginScreen() ) )return hr;
- // 告诉引擎,我下面要画3D的东西
- KM3D_Set3DView_Start(g_Globle.matWorld);
- // 开始画3D的东西
- KM3D_Set3DView_End();
- // 画3D的东西结束
- // 告诉引擎,我下面要画2D的东西
- KM3D_Set2DPlaneView_Start();
- // 开始画2D的东西
- KM3D_Set2DPlaneView_End();
- // 画2D的东西结束
- // 通知引擎说,我画完东西了,让其结束一下.意思就是说我要尿完了,你端个盆走吧
- if(FAILED (hr = KM3D_3D_EndScreen() ) )return hr;
- return S_OK;
- }
- // 处理窗口消息[所有的键盘鼠标事件,网络消息等等等等]
- LRESULT MainApp::MsgProc( HWND hWnd, UINT msg, WPARAM wParam,
- LPARAM lParam )
- {
- // 开始的时候,纪录以下鼠标位置
- // 在GameCursor种告诉引擎不知道鼠标位置,这个放在第一步处理
- switch( msg )
- {
- case WM_MOUSEMOVE:
- if( m_bActive )
- {
- POINT ptCursor;
- GetCursorPos( &ptCursor );
- if( g_pApp->GetAppIsWindow() )ScreenToClient( hWnd, &ptCursor );
- g_pGameCursor->SetPos(ptCursor);
- }
- break;
- case WM_SETCURSOR:
- {
- SetCursor( NULL );
- return 1;
- }
- break;
- }
-
- // 然后处理各个窗口的消息
- // 将这些window信息传递给相应的界面窗口
- switch(g_Globle.nGameStata)
- {
- case S_MAIN_MENU_WND:
- {
- if(g_pMainMenuWnd)
- {
- g_pMainMenuWnd->MsgProc(hWnd, msg, wParam, lParam);
- }
- }
- break;
- case S_LOADING_WND:
- case S_GAME_WND:
- break;
- }
- // 如果上面没有处理的消息,交给引擎处理以下,
- // 其实里面就只是处理的一些窗口大小变化,是否窗口激活隐藏
- // close窗口等信息
- // 如果你不愿意他处理,那么自己接管,不要调用下面的就可以了
- return KM3DScreen::MsgProc( hWnd, msg, wParam, lParam );
- }
复制代码 |
|