现在的位置: 首页 > 综合 > 正文

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

2013年08月14日 ⁄ 综合 ⁄ 共 8255字 ⁄ 字号 评论关闭

 

 在潜水很多天后,今天又有时间来这里写文章了。我今天写的文章是有关于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. /*--------------------------------------------------  
  8. 这里借鉴使用了Allen Sherrod的代码  
  9. 所有权归蒋轶民和Allen Sherrod所有  
  10. 详情请见《DirectX游戏开发终极指南》  
  11. ---------------------------------------------------*/  
  12. #include<d3d9.h>   
  13. #include<d3dx9.h>   
  14.   
  15. #pragma comment(lib, "d3d9.lib")   
  16. #pragma comment(lib, "d3dx9.lib")   
  17.   
  18. #define APPCLASS        "打方块游戏"   
  19. #define WINDOW_TITLE    "打方块游戏"   
  20. #define WINDOW_WIDTH    640   
  21. #define WINDOW_HEIGHT   480   
  22.   
  23.   
  24. // 函数的原型   
  25. bool InitializeD3D( HWND hWnd, bool fullscreen );   
  26. bool InitializeObjects( void );   
  27. void RenderScene( void );   
  28. void Shutdown( void );   
  29.   
  30. // Direct3D 对象和装置   
  31. LPDIRECT3D9 g_D3D = NULL;   
  32. LPDIRECT3DDEVICE9 g_D3DDevice = NULL;   
  33.   
  34. bool flagIncre = false;// 用来标记是颜色是否变量   
  35. short varColor = 0;// 一个全局变量,用来改变颜色,达到渐显的效果   
  36.   
  37. // 顶点缓存用来保存几何图形   
  38. LPDIRECT3DVERTEXBUFFER9 g_VertexBuffer = NULL;   
  39.   
  40. // 矩阵类   
  41. D3DXMATRIX g_projection;   
  42. D3DXMATRIX g_ViewMatrix;   
  43.   
  44. // 用来保存纹理的指针   
  45. LPDIRECT3DTEXTURE9 g_Texture = NULL;   
  46.   
  47. // 自定义的顶点结构,用来存储位图   
  48. // 其中tu、tv表示起始位置的宽度比和高度比   
  49. struct stD3DVertex   
  50. {   
  51.     float x, y, z;   
  52.     unsigned long color;   
  53.     float tu, tv;   
  54. };   
  55.   
  56. // 自定义的FVF   
  57. #define D3DFVF_VERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)   
  58.   
  59. // 自定义顶点对象,参数包括x,y,z,颜色和纹理坐标x,y   
  60. stD3DVertex rectData[6] =   
  61. {   
  62.     {-0.3f, -0.4f, 0.0f, D3DCOLOR_XRGB(0, 0, 0), 0.0f, 1.0f},   
  63.     {0.3f, -0.4f, 0.0f, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 1.0f},   
  64.     {0.3f, 0.4f, 0.0f, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0.0f},   
  65.   
  66.     {0.3f, 0.4f, 0.0f, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0.0f},   
  67.     {-0.3f, 0.4f, 0.0f, D3DCOLOR_XRGB(0, 0, 0), 0.0f, 0.0f},   
  68.     {-0.3f, -0.4f, 0.0f, D3DCOLOR_XRGB(0, 0, 0), 0.0f, 1.0f}   
  69. };   
  70.   
  71.   
  72. LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)   
  73. {   
  74.     switch(msg)   
  75.     {   
  76.     case WM_DESTROY:   
  77.         PostQuitMessage(0);   
  78.         return 0;   
  79.         break;   
  80.   
  81.     case WM_KEYUP:   
  82.         if(wParam == VK_ESCAPE) PostQuitMessage(0);   
  83.         break;   
  84.     }   
  85.   
  86.     return DefWindowProc(hWnd, msg, wParam, lParam);   
  87. }   
  88.   
  89. int WINAPI WinMain( HINSTANCE hInst, HINSTANCE prevhInst, LPSTR cmd, int show )   
  90. {   
  91.     // 注册窗口类   
  92.     WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc,   
  93.         0, 0, GetModuleHandle(NULL), NULL, NULL,   
  94.         NULL, NULL, APPCLASS, NULL };   
  95.   
  96.     RegisterClassEx(&wc);   
  97.   
  98.     // 创建窗口   
  99.     HWND hWnd = CreateWindow( APPCLASS, WINDOW_TITLE,   
  100.         WS_OVERLAPPEDWINDOW , 160, 40,   
  101.         WINDOW_WIDTH, WINDOW_HEIGHT, GetDesktopWindow(), NULL,   
  102.         wc.hInstance, NULL);   
  103.   
  104.     // 显示窗口   
  105.     ShowWindow(hWnd, SW_SHOWDEFAULT);   
  106.     UpdateWindow(hWnd);   
  107.   
  108.     // 初始化Direct3D   
  109.     if( InitializeD3D( hWnd, false ) )   
  110.     {   
  111.         // 进入消息循环   
  112.         MSG msg;   
  113.         ZeroMemory(&msg, sizeof(msg));   
  114.   
  115.         while(msg.message != WM_QUIT)   
  116.         {   
  117.             if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))   
  118.             {   
  119.                 TranslateMessage(&msg);   
  120.                 DispatchMessage(&msg);   
  121.             }   
  122.             else  
  123.             {   // 开始渲染   
  124.                 RenderScene();   
  125.             }   
  126.         }   
  127.     }   
  128.     else MessageBox( NULL, "程序初始化出错!""程序信息", MB_OK );   
  129.   
  130.     // 解除注册窗口   
  131.     UnregisterClass(APPCLASS, wc.hInstance);   
  132.     return 0;   
  133. }   
  134.   
  135. // 初始化D3D的函数   
  136. bool InitializeD3D( HWND hWnd, bool fullscreen )   
  137. {   
  138.     D3DDISPLAYMODE displayMode;   
  139.   
  140.     // 创建D3D对象   
  141.     g_D3D = Direct3DCreate9(D3D_SDK_VERSION);   
  142.     if( g_D3D == NULL ) return false;   
  143.   
  144.     // 获取电脑的显示模式   
  145.     if(FAILED( g_D3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &displayMode ) ) )   
  146.         return false;   
  147.   
  148.     // 启动一个结构体,为创建D3D设备做准备   
  149.     D3DPRESENT_PARAMETERS d3dpp;   
  150.     ZeroMemory(&d3dpp, sizeof(d3dpp));   
  151.   
  152.     if(fullscreen)   
  153.     {   
  154.         d3dpp.Windowed = FALSE;   
  155.         d3dpp.BackBufferWidth = 640;   
  156.         d3dpp.BackBufferHeight = 480;   
  157.     }   
  158.     else  
  159.         d3dpp.Windowed = TRUE;   
  160.     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;   
  161.     d3dpp.BackBufferFormat = displayMode.Format;   
  162.   
  163.     // 创建D3D设备   
  164.     if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,   
  165.         D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_D3DDevice)))   
  166.     {   
  167.         return false;   
  168.     }   
  169.   
  170.     // 初始化将要显示的对象   
  171.     if( !InitializeObjects() )   
  172.     {   
  173.         MessageBox( NULL, "载入初始化对象错误!""程序通知", MB_OK );   
  174.         return false;   
  175.     }   
  176.     return true;   
  177. }   
  178.   
  179. bool InitializeObjects( void )   
  180. {   
  181.     // 从文件中装载TGA图片   
  182.     if( D3DXCreateTextureFromFile(g_D3DDevice, "GIMP_Ubuntu_splash_screen.tga", &g_Texture) != D3D_OK )   
  183.         return false;   
  184.   
  185.     // 设置图片的状态   
  186.     g_D3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);   
  187.     g_D3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);   
  188.   
  189.     // 设置默认的渲染状态   
  190.     g_D3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);   
  191.     g_D3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);   
  192.   
  193.     // 设置投影状态   
  194.     D3DXMatrixPerspectiveFovLH( &g_projection, 45.0f, WINDOW_WIDTH/WINDOW_HEIGHT,   
  195.         0.1f, 1000.0f );   
  196.     g_D3DDevice->SetTransform( D3DTS_PROJECTION, &g_projection );   
  197.   
  198.     // 定义摄影机状态   
  199.     D3DXVECTOR3 cameraPos(0.0f, 0.0f, -1.0f);   
  200.     D3DXVECTOR3 lookAtPos(0.0f, 0.0f, 0.0f);   
  201.     D3DXVECTOR3 upDir(0.0f, 1.0f, 0.0f);   
  202.   
  203.     // 建立矩阵   
  204.     D3DXMatrixLookAtLH( &g_ViewMatrix, &cameraPos, &lookAtPos, &upDir );   
  205.   
  206.     // 清除后台缓存   
  207.     g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET,   
  208.         D3DCOLOR_XRGB(0,0,0), 1.0f, 0);   
  209.     return true;   
  210. }   
  211.   
  212.   
  213. void RenderScene( void )   
  214. {   
  215.     if ( flagIncre == false && varColor < 255 )// 让颜色逐渐达到255(白色)   
  216.         varColor+=3;// 颜色递增,结果越明亮   
  217.     if ( flagIncre == false && varColor >=255 )   
  218.     {   
  219.         flagIncre = true;// 标记为已经变亮过   
  220.         Sleep( 2500 );// 画面停止2.5秒,让用户仔细看游戏图标   
  221.     }   
  222.     if ( flagIncre == true && varColor > 0 )   
  223.         varColor-=3;// 颜色递减,结果越明暗   
  224.   
  225.     int i;   
  226.     for ( i = 0; i < 6; rectData[i].color = D3DCOLOR_XRGB( varColor, varColor, varColor), i++ );   
  227.   
  228.     // 顶点顶点缓存   
  229.     if(FAILED(g_D3DDevice->CreateVertexBuffer(sizeof(rectData), 0, D3DFVF_VERTEX, D3DPOOL_DEFAULT, &g_VertexBuffer, NULL))) return;   
  230.   
  231.     // 锁住顶点缓存,开始在后台缓存上绘制   
  232.     void *ptr;   
  233.     if( FAILED( g_VertexBuffer->Lock( 0, sizeof( rectData ), ( void** ) &ptr, 0 ) ) ) return;   
  234.     memcpy ( ptr, rectData, sizeof ( rectData ) );   
  235.     g_VertexBuffer->Unlock();// 解锁   
  236.   
  237.     // 开始渲染   
  238.     g_D3DDevice->BeginScene();   
  239.   
  240.     // 应用视角   
  241.     g_D3DDevice->SetTransform(D3DTS_VIEW, &g_ViewMatrix);   
  242.   
  243.     // 绘制矩形   
  244.     g_D3DDevice->SetTexture(0, g_Texture);   
  245.     g_D3DDevice->SetStreamSource(0, g_VertexBuffer,   
  246.         0, sizeof(stD3DVertex));   
  247.     g_D3DDevice->SetFVF(D3DFVF_VERTEX);   
  248.     g_D3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);   
  249.   
  250.     // 结束渲染   
  251.     g_D3DDevice->EndScene();   
  252.   
  253.     // D显示场景   
  254.     g_D3DDevice->Present(NULL, NULL, NULL, NULL);   
  255. }   
  256.   
  257. // 释放所有的对象   
  258. void Shutdown( void )   
  259. {   
  260.     if(g_D3DDevice != NULL) g_D3DDevice->Release();   
  261.     g_D3DDevice = NULL;   
  262.   
  263.     if(g_D3D != NULL) g_D3D->Release();   
  264.     g_D3D = NULL;   
  265.   
  266.     if(g_VertexBuffer != NULL) g_VertexBuffer->Release();   
  267.     g_VertexBuffer = NULL;   
  268.   
  269.     if(g_Texture != NULL) g_Texture->Release();   
  270.     g_Texture = NULL;   
  271. }  

程序的截图如下所示:


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

抱歉!评论已关闭.