3D游戏设计与开发基于DXUT应用程序框架的DirectX开发.docx
- 文档编号:4461880
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:40
- 大小:3.21MB
3D游戏设计与开发基于DXUT应用程序框架的DirectX开发.docx
《3D游戏设计与开发基于DXUT应用程序框架的DirectX开发.docx》由会员分享,可在线阅读,更多相关《3D游戏设计与开发基于DXUT应用程序框架的DirectX开发.docx(40页珍藏版)》请在冰豆网上搜索。
3D游戏设计与开发基于DXUT应用程序框架的DirectX开发
毕业设计
3D游戏设计与开发
基于DXUT应用程序框架的DirectX开发
【摘要】视频游戏产业在娱乐业所占的比例越来越大,根据美国去年的调查显示,2009至2010年美国的电子游戏产业的营业额已经超过了好莱坞的电影票房收入。
可以看出这个市场有着巨大的潜力,当然在我国也不例外。
但是由于种种已知原因,这个行业在我国还处于比较落后的局面,缺乏各种核心的技术,尤其是当游戏引擎——这种集软件行业顶尖智慧于一身的开发形式面世后,大大加速了各种游戏的开发效率。
而大部分的游戏引擎技术都掌握在欧美手里,这种软件的开发难度又不亚于操作系统的编写难度,几家核心游戏引擎的开发商也因此大大的赚了个盆丰钵满。
既然要为了这个远大的目标而奋斗,一个基于DirectX技术所开发的3D游戏实验性项目便成为了我这次的选题
【关键词】游戏引擎;图形学;自主开发DirectX
1引言
1.1现今游戏市场背景
从某种意义上来说,电子游戏这的开发市场主要以欧美一些主流游戏开发商为主,包括了市面上现在流行的单机或网络游戏都是如此,国内市场鲜有沾光。
造成这种局面的原因比较复杂,一是国内在计算机专业领域起步非常晚,尤其是计算机娱乐和多媒体这个领域更是如此,二是国内的游戏市场始终打不开局面。
在PC平台上的单机游戏正热火朝天的时候,国内其实也有点这种乘胜追击的势头,比如当年以仙剑为主的一系列武侠RPG游戏也给了我们这一代人不少少年时候的美好回忆。
可惜当时国内的单机游戏市场黯淡无光的主要原因是因为被盗版这个始终挥之不去的毒瘤给毁了,国内游戏制作人只能看着国外的同行们一个一个的成为百万富翁,而自己却只能改行或者默默的成为角落里的角色而暗自悲哀。
可到了网游盛行的年代,虽然制作以及技术核心以国外为主的局面仍然没有大的改观,但是国内网游制作商以国内玩家这个特殊的游戏群体,以及其巨大的市场潜在价值为基础,以投机取巧的商业运营方式,还是能在这个大蛋糕上赚得一部分份额的。
1.2解决的办法
但是问题始终是问题,不能因为其能赚钱而忽略了国内游戏制作商缺乏核心技术的巨大漏洞。
如果说现在的国内游戏市场靠着大部分休闲/非核心玩家的大量涌入的道具收费方式得意谋取利润的话,那么到了若干年后,主流游戏玩家们成长为核心游戏玩家,他们追求游戏质量,游戏可玩性,而不是现今的泡菜游戏博一一乐的游戏理念,那么这种打一枪换一个地方的游戏运营方式和理念迟早都是要被淘汰在历史之中的。
所以,要培养国内自己的核心游戏开发团队和游戏人才输出现在来说是一个非常有前瞻性并且大胆的人才投资方向。
1.3DirectX的优势
DirectX在过去的数十载中已经逐步稳固的进化为游戏开发者们在微软的Windows平台上开发游戏的首选开发接口。
每一代的DirectX都带来为新的硬件提供的图形加速支持,使得游戏开发人员能以惊人的速度前进着。
图1利用DirectX制作的逼真的游戏场景
DirectX有着多种开发接口,Direct3D是基于HAL硬件加速的图形接口,DirectSound是声音接口,DirectInput可以用与微软自家的游戏机Xbox的输入系统等等。
DirectX很底层,但是也很强大,利用它几乎可以制作所以令人乍舌的视觉效果和性能卓越的精彩游戏。
而且微软也在不断的更新着DirectX,使它支持更多的特效,更多的功能,更新的软硬件架构。
在推动了游戏发展的同时,也成为了硬件市场发展的强心针,在为玩家带来了快乐的同时,也为商家带来了更多利润。
2本毕业设计所开发的游戏
2.1第三人称跟随视角类游戏
图2著名的TPS——《战争机器》
TPS(第三人称射击)游戏是我个人比较喜欢的类型,第三人称跟随视角的游戏一般比较适合做ARPG或者MMORPG游戏,玩家的视角被固定在自己的角色身后,这样可以随时看到自己的人物的装扮,以产生一种满足感。
相对于第一人称射击类游戏来说,可以看到自己身边和身后的一些状况,玩家能观察到自己角色流畅的动作,增加了游戏整体的流畅感与爽快感。
对于快节奏的射击类游戏来说也是相当重要的环节。
而且很重要的一点,第三人称跟随视角的动作类游戏不容易使有3D眩晕症的玩家头晕。
所以第三人称视角适合用于做ARPG,MMORPG,TPS这几类游戏,也使得越来越多的网游厂商为了吸引更多核心/非核心玩家而采取第三人称视角,例如《魔兽世界》等游戏。
图3著名网游《魔兽世界》截图
图4游戏截图
2.2游戏简介
图5游戏失败画面
游戏操作很简单,用只要用键盘就应付所有操作
∙W向正前方前进
∙S向后方后退
∙A向左平移
∙D向右平移
∙方向上向上爬升
∙方向下向下下降
∙方向左向左旋转
∙方向右向右旋转
∙空格开炮
游戏方式就是通过移动和旋转躲避敌人的子弹,然后向敌人开火击落他们。
当击中敌机的时候敌机会死亡。
你一共有4格生命值,当生命值被耗光时游戏结束。
3 具体设计部分
3.1DirectXSDK的安装与开发环境配置
开发环境visualStudio2010
图形界面接口DirectSDK开发包(March2009&Jun2010)
语言C++
图6visualstudio2010开发界面
3.2游戏的架构
大家都知道,计算机的显示器是平面的,也就是说是完全二维,那么要如何表现如同现实世界中的三维效果呢?
期中最基本的原理即采用了透视。
通俗的讲,透视是引入了现实世界中近大远小的视觉效果,对于计算机图形来说,即加入了场景深度的概念,当我们自带看到显示器上的图像时,便产生了错觉[1]。
3.2.1游戏所采用的应用程序框架
图7DXUT框架
DirectX提供了基础的图形接口,但使用起来非常繁琐,而且功能比较有限。
DirectX提供了一个叫做DXUT(也称为sampleframework)的应用程序框架,将一些重复的框架性代码封装起来作为应用程序框架,这样程序员就可以将更多精力投入到核心代码的开发,从而大大提高开发的效率。
[1]
相较于DirectXAPI,使用DXUT框架有许多方便之处。
代码的简洁性,程序结构的层次性,处理消息循环,处理设备事件等。
DXUT像windows的窗体一样,使用事件回调的机制,也就是说将DirectX里的渲染当作一些事件来处理,对于不同的事件回调使用不同的回调函数。
表1一些必要的DXUT回调函数
boolCALLBACKIsDeviceAcceptable()
设备能力检查
boolCALLBACKModifyDeviceSettings()
修改Direct3D渲染设备设置
HRESULTCALLBACKOnCreateDevice()
创建管理内存资源对象
HRESULTCALLBACKOnResetDevice()
创建默认内存类型资源对象
voidCALLBACKOnFrameMove()
更新场景
voidCALLBACKOnFrameRender()
渲染场景
LRESULTCALLBACKMsgProc()
消息处理
voidCALLBACKOnLostDevice()
释放在OnResetDevice()中创建的资源和对象
voidCALLBACKOnDestroyDevice()
释放在OnCreateDevice()中创建的资源和对象
3.2.2创建框架
打开DirectXSampleBrowser,找到EmptyProject,点击InstallProject,选择保存路径点确定,然后用visualstudio打开工程
图8samplebrowser
这个框架可以直接被编译生成一个窗口。
因为除了渲染场景的OnFrameRender()以外其他回调函数体内都是空的,所以这个窗口相当于一个”helloworld”窗口。
图9空白的窗口
像所有其他C++的窗口程序一样,DirectX的程序也需要一个主函数作为函数入口
函数定义如下
INTWINAPIWinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
#ifdefined(DEBUG)|defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
#endif
DXUTSetCallbackDeviceCreated(OnCreateDevice);
DXUTSetCallbackDeviceReset(OnResetDevice);
DXUTSetCallbackDeviceLost(OnLostDevice);
DXUTSetCallbackDeviceDestroyed(OnDestroyDevice);
DXUTSetCallbackMsgProc(MsgProc);
DXUTSetCallbackKeyboard(KeyboardProc);
DXUTSetCallbackFrameRender(OnFrameRender);
DXUTSetCallbackFrameMove(OnFrameMove);
DXUTSetCursorSettings(true,true);
InitApp();
DXUTInit(true,true,true);
DXUTCreateWindow(L"NewGame");
DXUTCreateDevice(D3DADAPTER_DEFAULT,false,0,0,IsDeviceAcceptable,ModifyDeviceSettings);
DXUTMainLoop();
returnDXUTGetExitCode();
}
DXUT框架有着许多它自己的很好的特性也是我使用它的一大原因。
其中支持一些DirectX自定义的控件得以在制作游戏时可以使用一些很方便的比如按钮,滑动条,文本框,下拉框这样的操作。
为了支持控件,需要添加一个回调函数OnGUIEvent();函数原型如下
voidCALLBACKOnGUIEvent(UINTnEvent,intnControlID,CDXUTControl*pControl,void*pUserContext)
图10控件使用效果图
使用控件后,可以在游戏内添加按钮,以完全可视化的操作方式来设计游戏的UI界面,让交互变得不再生硬。
图11DXUT即时文本效果
3.3程序逻辑
程序从主函数入口进入,第一部先初始化全局变量:
检查设备可用性:
boolCALLBACKIsD3D9DeviceAcceptable(D3DCAPS9*pCaps,D3DFORMATAdapterFormat,D3DFORMATBackBufferFormat,boolbWindowed,void*pUserContext)
接着把当前设备修改为默认设备,此函数也为回调函数:
boolCALLBACKModifyDeviceSettings(DXUTDeviceSettings*pDeviceSettings,void*pUserContext)
创建设备,如切换全屏,或者其他属性时调用此函数来设置设备属性。
在此创建的资源在OnDestroyDevice()函数中销毁:
HRESULTCALLBACKOnD3D9CreateDevice(IDirect3DDevice9*pd3dDevice,constD3DSURFACE_DESC*pBackBufferSurfaceDesc,void*pUserContext)
重置设备,此回调函数在每次变换设备属性的时候都会被调用,在此创建的资源在OnLostDevice()函数中销毁:
HRESULTCALLBACKOnD3D9ResetDevice(IDirect3DDevice9*pd3dDevice,constD3DSURFACE_DESC*pBackBufferSurfaceDesc,void*pUserContext)
游戏事件循环,在此进行游戏所有事件的循环检测,以每一帧为更新场景的检测单元,不过最好不要在这里对场景渲染:
voidCALLBACKOnFrameMove(doublefTime,floatfElapsedTime,void*pUserContext)
游戏渲染,对图形渲染,包括顶点,光照,纹理,界面,等的函数,以帧为单位更新帧缓冲器的所有数据:
voidCALLBACKOnD3D9FrameRender(IDirect3DDevice9*pd3dDevice,doublefTime,floatfElapsedTime,void*pUserContext)
用于销毁在OnResetDevice()中创建的资源:
voidCALLBACKOnD3D9LostDevice(void*pUserContext)
用于销毁在OnCreateDevice()中创建的资源:
voidCALLBACKOnD3D9DestroyDevice(void*pUserContext)
消息事件循环,当窗口接受外部消息传入时,回调函数就会接受信息然后传给DirectX并处理给程序:
LRESULTCALLBACKMsgProc(HWNDhWnd,UINTuMsg,WPARAMwParam,LPARAMlParam,bool*pbNoFurtherProcessing,void*pUserContext)
图12一个最简单的流程,本游戏就是基于这个框架
而接下来要做的,就是往框架内添加游戏所自定义的的代码。
3.4游戏事件循环详解
intAPIENTRYWinMain(HINSTANCEhInstance,
HINSTANCEhPrevInstance,
LPTSTRlpCmdLine,
intnCmdShow)
{
srand(timeGetTime());
HWNDhWnd;
MSGmsg;
IDirect3DDevice9*Device;
CGameEngine_App*GameEngine_App=newCGameEngine_App;
GameEngine_App->InitD3D(&Device,"Game",hInstance,(int)width,(int)height,true);
hWnd=GameEngine_App->GetHWnd();
GetWindowRect(hWnd,&rect);
Game*game=newGame(Device,hWnd,hInstance);
while(true)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message==WM_QUIT)
{
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
game->GameRun(Device);
}
UnregisterClass("game",hInstance);
returntrue;
}
这是一个理想的游戏循环入口,它包括了设备的创建,各种内存变量的初始化,应用程序窗口的创建,游戏对象的创建,游戏内部的循环开始,消息的循环等一系列基本过程,十分言简意赅。
当然这只是一个模型,伪代码,游戏真正的游戏事件并不是基于这个框架的,但是用这个例子可以将制作游戏的整体思路表达的很清晰明了,在使用DirextX自带的框架时可以更加得心应手。
3.4.1全局变量的声明
ID3DXFont*g_pFont=NULL;//用来建立窗口上的字体
ID3DXSprite*g_pTextSprite=NULL;//用来加快窗口上的字体输出
ID3DXEffect*g_pEffect=NULL;//D3DX响应接口
boolg_bShowHelp=true;//用来决定是否显示窗口上的Help的字
CDXUTDialogResourceManagerg_DialogResourceManager;//共享资源对话框管理器
CD3DSettingsDlgg_SettingsDlg;//设备设置对话框
CDXUTDialogg_HUD;//控制窗口上右上角3特按钮
CDXUTDialogg_SampleUI;//控制窗口右下角其他的UI
FLOATg_yaw_angle;//绕y轴旋转角
ID3DXMatrixStack*g_pHeroMat;//存储转换矩阵的栈
Hero*g_pHero;//主角模型
CMesh*g_pFloor;//地板
CBoxsky*g_pSky;//天空盒子
Snow*snow;//雪花
Enemy*g_pEnemy[EnemyNum];//敌人
Game*game;//判断游戏事件变量
D3DXMATRIXg_pHeromatWorld;//主角世界矩阵
UserInputg_UserInput;//存储玩家输入的结构
D3DXVECTOR3g_HeroPos;//主角三维位置
boolgameover;//游戏失败
boolwin;//胜利
inthit;//被击中的敌机数量
WCHARg_strShow[100];
全局变量的声明包括了很多方面变量的创建,控制游戏事件检测的布尔型变量gameover,当它被声明为false时表明游戏尚未结束,渲染正常的游戏画面,反之则渲染游戏结束时的画面;g_pHeromatWorld是一个D3DXMATRIX的4*4阶矩阵类型变量,用来存储世界矩阵变换;g_HeroPos是一个D3DXVECTOR3的3维向量变量,存放一个向量值,代表了主角在三维世界里的方向和位置。
3.4.2游戏状态初始化
g_SettingsDlg.Init(&g_DialogResourceManager);
g_HUD.Init(&g_DialogResourceManager);
g_SampleUI.Init(&g_DialogResourceManager);
g_HUD.SetCallback(OnGUIEvent);intiY=10;
g_HUD.AddButton(IDC_TOGGLEREF,L"ToggleREF(F3)",35,iY+=94,125,22);
g_HUD.AddButton(IDC_CHANGEDEVICE,L"Changedevice(F2)",35,iY+=24,125,22,VK_F2);
g_SampleUI.SetCallback(OnGUIEvent);iY=10;
g_HeroPos.x=0.0f;
g_HeroPos.y=5.5f;
g_HeroPos.z=12.0f;
g_yaw_angle=0.0f;
gameover=false;
win=false;
hit=0;
InitApp()函数主要使一些游戏画面的初始数据进行初始化更新,如:
∙控件指针的初始化
∙界面的文字显示
∙按钮控件的初始化
∙角色模型的定位
∙方向的设置
∙游戏失败判断的初始化为否
∙游戏胜利判断初始化为否
等一系列操作。
3.4.3设备参数创建
HRESULTCALLBACKOnCreateDevice(IDirect3DDevice9*pd3dDevice,constD3DSURFACE_DESC*pBackBufferSurfaceDesc,void*pUserContext)
函数主要对一些设备分配内存空间,还有为游戏对象分配内存空间
g_pHero=newHero();
for(inti=0;i g_pEnemy[i]=newEnemy(); g_pFloor=newCMesh(); g_pSky=newCBoxsky(); snow=newSnow(); game=newGame(); 在这里,为游戏主角飞机对象指针g_pHero在内存中创建了一个Hero类型大小的空间。 g_pEnemy数组是一个存放敌人数量的数组,数组内每一个数据对象都要分配Enemy类型的内存空间。 g_pFloor是地图的地板模型,它是一个CMesh网格模型类型的对象。 g_pSky是天空盒子,是我用来制作天空和陆地界限的方式。 snow是屏幕中用雪花纷飞来表示的粒子效果,用的是Snow类型来分配内存。 game是一个用来显示最后游戏失败或者胜利时显示贴图的对象,使用的是Game类型。 3.4.4重置设备属性 HRESULTCALLBACKOnResetDevice(IDirect3DDevice9*pd3dDevice,constD3DSURFACE_DESC*pBackBufferSurfaceDesc,void*pUserContext) 设定场景内的材质值 这里将材质设定为漫反射材质 D3DMATERIAL9mtrl; ZeroMemory(&mtrl,sizeof(D3DMATERIAL9)); mtrl.Diffuse.r=mtrl.Ambient.r=1.0f; mtrl.Diffuse.g=mtrl.Ambient.g=1.0f; mtrl.Diffuse.b=mtrl.Ambient.b=1.0f; mtrl.Diffuse.a=mtrl.Ambient.a=0.0f; pd3dDevice->SetMaterial(&mtrl); 设定世界矩阵以及初始化 D3DXMATRIXmatIdentity; D3DXMatrixIdentity(&matIdentity); pd3dDevice->SetTransform(D3DTS_WORLD,&matIdentity); 设定投影的相关信息,以决定窗口的视野范围 D3DXMATRIXmatProj; FLOATfAspect=((FLOAT)pBackBufferSurfaceDesc->Width)/pBackBufferSurfaceDesc->Height; D3DXMatrixPerspecti
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 游戏 设计 开发 基于 DXUT 应用程序 框架 DirectX