设计DirectX游戏开头画面淡入淡出的效果

DirectX游戏开头画面实现
本文介绍了使用DirectX实现游戏开头画面的详细过程,包括如何通过改变颜色来达到淡入淡出的效果,以及具体的代码实现。

在潜水很多天后,今天又有时间来这里写文章了。我今天写的文章是有关于DirectX游戏开头画面的,大家肯定看过一些有名的游戏,它们在开头肯定是会显示游戏公司的商标和游戏的图标。但是为了给大家一种电影的感觉,他们往往会逐渐显示这些二维图片。这种显示方式叫做淡入淡出(fade in and fade out)。下面我就用一个例子程序来说说我是怎么使用DirectX来实现这个效果的。
其实在我学习这个效果的时候,我也想了很多。起初我是想用雾(fog)这种特效来模拟的。但是我突然发现使用雾的特效要设置很多很多的参数,而且我在试验的过程中往往得不到应有的效果。这可使我非常失望。原本想通过一个循环,使雾的颜色随着时间的变化而改变,这样的出来的显示效果应该是很好的,可是实际情况并非如此。我的第一种方法泡了汤。
第二种方法是试图使用一个小小的视频来进行显示。我曾经为了实现这个小小的功能,去了有着悠久历史的gamedev.net网站进行询问。来自世界各地的游戏开发者给了我很多答案。其中有个人给我推荐了使用BINK(见http://baike.baidu.com/view/1313785.htm)来进行游戏开场动画的设计。不过要掌握BINK的话,还要很长的一段路,所以第二种方案也没有被我采纳。
最后没有办法。我想要的效果是,只要使用载入一张图片,然后对图片纹理进行不同的渲染,这样不就行了?我这样想着,对下面这样的结构进行分析。
struct stD3DVertex
{
float x, y, z;
unsigned long color;
float tu, tv;
};
这个结构和我以前使用的结构有所不同,这个结构多了tu和tv这两个变量。查了查书,知道这两个变量是描述纹理坐标起始位置和结束位置的。这些值是0~1之间的任意值。而且我仔细地研究了一下,前面三个xyz变量中,有两个变量x、y是表述载入图像显示的位置的,理论上可以无限大还是无限小,但是过大或过小会使图像看不清,所以应在-0.5到0.5之间是最清楚的。然后以颜色为变量,简单地设置一下循环,诶,效果出来啦。
下面就是我的程序的所有代码。

Code:
  1. /*--------------------------------------------------
  2. 蒋轶民制作:E-mail:jiangcaiyang123@163.com
  3. 文件名:GameInit.cpp
  4. 作用:加载游戏片头动画
  5. ---------------------------------------------------*/
  6. /*--------------------------------------------------
  7. 这里借鉴使用了AllenSherrod的代码
  8. 所有权归蒋轶民和AllenSherrod所有
  9. 详情请见《DirectX游戏开发终极指南》
  10. ---------------------------------------------------*/
  11. #include<d3d9.h>
  12. #include<d3dx9.h>
  13. #pragmacomment(lib,"d3d9.lib")
  14. #pragmacomment(lib,"d3dx9.lib")
  15. #defineAPPCLASS"打方块游戏"
  16. #defineWINDOW_TITLE"打方块游戏"
  17. #defineWINDOW_WIDTH640
  18. #defineWINDOW_HEIGHT480
  19. //函数的原型
  20. boolInitializeD3D(HWNDhWnd,boolfullscreen);
  21. boolInitializeObjects(void);
  22. voidRenderScene(void);
  23. voidShutdown(void);
  24. //Direct3D对象和装置
  25. LPDIRECT3D9g_D3D=NULL;
  26. LPDIRECT3DDEVICE9g_D3DDevice=NULL;
  27. boolflagIncre=false;//用来标记是颜色是否变量
  28. shortvarColor=0;//一个全局变量,用来改变颜色,达到渐显的效果
  29. //顶点缓存用来保存几何图形
  30. LPDIRECT3DVERTEXBUFFER9g_VertexBuffer=NULL;
  31. //矩阵类
  32. D3DXMATRIXg_projection;
  33. D3DXMATRIXg_ViewMatrix;
  34. //用来保存纹理的指针
  35. LPDIRECT3DTEXTURE9g_Texture=NULL;
  36. //自定义的顶点结构,用来存储位图
  37. //其中tu、tv表示起始位置的宽度比和高度比
  38. structstD3DVertex
  39. {
  40. floatx,y,z;
  41. unsignedlongcolor;
  42. floattu,tv;
  43. };
  44. //自定义的FVF
  45. #defineD3DFVF_VERTEX(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
  46. //自定义顶点对象,参数包括x,y,z,颜色和纹理坐标x,y
  47. stD3DVertexrectData[6]=
  48. {
  49. {-0.3f,-0.4f,0.0f,D3DCOLOR_XRGB(0,0,0),0.0f,1.0f},
  50. {0.3f,-0.4f,0.0f,D3DCOLOR_XRGB(0,0,0),1.0f,1.0f},
  51. {0.3f,0.4f,0.0f,D3DCOLOR_XRGB(0,0,0),1.0f,0.0f},
  52. {0.3f,0.4f,0.0f,D3DCOLOR_XRGB(0,0,0),1.0f,0.0f},
  53. {-0.3f,0.4f,0.0f,D3DCOLOR_XRGB(0,0,0),0.0f,0.0f},
  54. {-0.3f,-0.4f,0.0f,D3DCOLOR_XRGB(0,0,0),0.0f,1.0f}
  55. };
  56. LRESULTWINAPIMsgProc(HWNDhWnd,UINTmsg,WPARAMwParam,LPARAMlParam)
  57. {
  58. switch(msg)
  59. {
  60. caseWM_DESTROY:
  61. PostQuitMessage(0);
  62. return0;
  63. break;
  64. caseWM_KEYUP:
  65. if(wParam==VK_ESCAPE)PostQuitMessage(0);
  66. break;
  67. }
  68. returnDefWindowProc(hWnd,msg,wParam,lParam);
  69. }
  70. intWINAPIWinMain(HINSTANCEhInst,HINSTANCEprevhInst,LPSTRcmd,intshow)
  71. {
  72. //注册窗口类
  73. WNDCLASSEXwc={sizeof(WNDCLASSEX),CS_CLASSDC,MsgProc,
  74. 0,0,GetModuleHandle(NULL),NULL,NULL,
  75. NULL,NULL,APPCLASS,NULL};
  76. RegisterClassEx(&wc);
  77. //创建窗口
  78. HWNDhWnd=CreateWindow(APPCLASS,WINDOW_TITLE,
  79. WS_OVERLAPPEDWINDOW,160,40,
  80. WINDOW_WIDTH,WINDOW_HEIGHT,GetDesktopWindow(),NULL,
  81. wc.hInstance,NULL);
  82. //显示窗口
  83. ShowWindow(hWnd,SW_SHOWDEFAULT);
  84. UpdateWindow(hWnd);
  85. //初始化Direct3D
  86. if(InitializeD3D(hWnd,false))
  87. {
  88. //进入消息循环
  89. MSGmsg;
  90. ZeroMemory(&msg,sizeof(msg));
  91. while(msg.message!=WM_QUIT)
  92. {
  93. if(PeekMessage(&msg,NULL,0U,0U,PM_REMOVE))
  94. {
  95. TranslateMessage(&msg);
  96. DispatchMessage(&msg);
  97. }
  98. else
  99. {//开始渲染
  100. RenderScene();
  101. }
  102. }
  103. }
  104. elseMessageBox(NULL,"程序初始化出错!","程序信息",MB_OK);
  105. //解除注册窗口
  106. UnregisterClass(APPCLASS,wc.hInstance);
  107. return0;
  108. }
  109. //初始化D3D的函数
  110. boolInitializeD3D(HWNDhWnd,boolfullscreen)
  111. {
  112. D3DDISPLAYMODEdisplayMode;
  113. //创建D3D对象
  114. g_D3D=Direct3DCreate9(D3D_SDK_VERSION);
  115. if(g_D3D==NULL)returnfalse;
  116. //获取电脑的显示模式
  117. if(FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&displayMode)))
  118. returnfalse;
  119. //启动一个结构体,为创建D3D设备做准备
  120. D3DPRESENT_PARAMETERSd3dpp;
  121. ZeroMemory(&d3dpp,sizeof(d3dpp));
  122. if(fullscreen)
  123. {
  124. d3dpp.Windowed=FALSE;
  125. d3dpp.BackBufferWidth=640;
  126. d3dpp.BackBufferHeight=480;
  127. }
  128. else
  129. d3dpp.Windowed=TRUE;
  130. d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
  131. d3dpp.BackBufferFormat=displayMode.Format;
  132. //创建D3D设备
  133. if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,
  134. D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&g_D3DDevice)))
  135. {
  136. returnfalse;
  137. }
  138. //初始化将要显示的对象
  139. if(!InitializeObjects())
  140. {
  141. MessageBox(NULL,"载入初始化对象错误!","程序通知",MB_OK);
  142. returnfalse;
  143. }
  144. returntrue;
  145. }
  146. boolInitializeObjects(void)
  147. {
  148. //从文件中装载TGA图片
  149. if(D3DXCreateTextureFromFile(g_D3DDevice,"GIMP_Ubuntu_splash_screen.tga",&g_Texture)!=D3D_OK)
  150. returnfalse;
  151. //设置图片的状态
  152. g_D3DDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
  153. g_D3DDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
  154. //设置默认的渲染状态
  155. g_D3DDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
  156. g_D3DDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
  157. //设置投影状态
  158. D3DXMatrixPerspectiveFovLH(&g_projection,45.0f,WINDOW_WIDTH/WINDOW_HEIGHT,
  159. 0.1f,1000.0f);
  160. g_D3DDevice->SetTransform(D3DTS_PROJECTION,&g_projection);
  161. //定义摄影机状态
  162. D3DXVECTOR3cameraPos(0.0f,0.0f,-1.0f);
  163. D3DXVECTOR3lookAtPos(0.0f,0.0f,0.0f);
  164. D3DXVECTOR3upDir(0.0f,1.0f,0.0f);
  165. //建立矩阵
  166. D3DXMatrixLookAtLH(&g_ViewMatrix,&cameraPos,&lookAtPos,&upDir);
  167. //清除后台缓存
  168. g_D3DDevice->Clear(0,NULL,D3DCLEAR_TARGET,
  169. D3DCOLOR_XRGB(0,0,0),1.0f,0);
  170. returntrue;
  171. }
  172. voidRenderScene(void)
  173. {
  174. if(flagIncre==false&&varColor<255)//让颜色逐渐达到255(白色)
  175. varColor+=3;//颜色递增,结果越明亮
  176. if(flagIncre==false&&varColor>=255)
  177. {
  178. flagIncre=true;//标记为已经变亮过
  179. Sleep(2500);//画面停止2.5秒,让用户仔细看游戏图标
  180. }
  181. if(flagIncre==true&&varColor>0)
  182. varColor-=3;//颜色递减,结果越明暗
  183. inti;
  184. for(i=0;i<6;rectData[i].color=D3DCOLOR_XRGB(varColor,varColor,varColor),i++);
  185. //顶点顶点缓存
  186. if(FAILED(g_D3DDevice->CreateVertexBuffer(sizeof(rectData),0,D3DFVF_VERTEX,D3DPOOL_DEFAULT,&g_VertexBuffer,NULL)))return;
  187. //锁住顶点缓存,开始在后台缓存上绘制
  188. void*ptr;
  189. if(FAILED(g_VertexBuffer->Lock(0,sizeof(rectData),(void**)&ptr,0)))return;
  190. memcpy(ptr,rectData,sizeof(rectData));
  191. g_VertexBuffer->Unlock();//解锁
  192. //开始渲染
  193. g_D3DDevice->BeginScene();
  194. //应用视角
  195. g_D3DDevice->SetTransform(D3DTS_VIEW,&g_ViewMatrix);
  196. //绘制矩形
  197. g_D3DDevice->SetTexture(0,g_Texture);
  198. g_D3DDevice->SetStreamSource(0,g_VertexBuffer,
  199. 0,sizeof(stD3DVertex));
  200. g_D3DDevice->SetFVF(D3DFVF_VERTEX);
  201. g_D3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,2);
  202. //结束渲染
  203. g_D3DDevice->EndScene();
  204. //D显示场景
  205. g_D3DDevice->Present(NULL,NULL,NULL,NULL);
  206. }
  207. //释放所有的对象
  208. voidShutdown(void)
  209. {
  210. if(g_D3DDevice!=NULL)g_D3DDevice->Release();
  211. g_D3DDevice=NULL;
  212. if(g_D3D!=NULL)g_D3D->Release();
  213. g_D3D=NULL;
  214. if(g_VertexBuffer!=NULL)g_VertexBuffer->Release();
  215. g_VertexBuffer=NULL;
  216. if(g_Texture!=NULL)g_Texture->Release();
  217. g_Texture=NULL;
  218. }

程序的截图如下所示:


程序效果还是挺好的,这里需要载入GIMP_Ubuntu_splash_screen.tga文件。这个文件是我使用ubuntu操作系统自带的图片进行的格式转换。顺便说说,ubuntu操作系统下的ginp的确很好,好得能和windows下的photoshop相媲美!
好了,今天我的工作就是这样了。下一次我想制作的是游戏开头的动画,当然不是载入的那种啦,我是想用DirectX的图元进行显示,当然这要花费我更多的时间。不过我最近把我所有的作业都完成了,相信我还是有信心在近日完成的!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值