使用DirectX让进行Alpha混合的子图形移动(精灵动画)

来源:互联网 发布:数据分析师需要的技能 编辑:程序博客网 时间:2024/04/27 18:36

使用DirectX让进行Alpha混合的子图形移动(精灵动画)
 最近我在二维动画的问题上总是不得其解。因为没有进行Alpha混合的二维动画,在外表上一定会很难看。所以我没有办法,只好四处求解。但是好像大家都没有给出我满意的答案。还好,我在一个源码库(http://www.hackchina.com/)中搜索到了一个示例程序,这个示例程序做得真的好,很逼真。所以我一定要把它拿来进行剖析。在了解到了我必须抛弃以前的surface结构后,我毅然决然地使用了例子中的sprite结构体。这样好了,我左试右试,最后终于成功了。为此我自己又做了一个tga图,和自己用Easy Paint Tool SAI修改的一个tga图。这样的话,我的演示程序就非常得好看了。

 下面就是我的MainFrame.cpp文件:
 

Code:
  1. /*---------------------------------------------------------------------------  
  2. 蒋轶民制作 E-mail:jiangcaiyang123@163.com  
  3. 文件名:MainFrame.cpp  
  4. 作用:子图像和Alpha融合的主框架  
  5. ----------------------------------------------------------------------------*/  
  6. /*--------------------------------------------------------------------------*/  
  7.   
  8. // 头文件   
  9. #include<windows.h>   
  10. #include<d3d9.h>   
  11. #include<d3dx9.h>   
  12. #include<stdio.h>   
  13.   
  14. // 库文件   
  15. #pragma comment( lib, "d3d9.lib")   
  16. #pragma comment( lib, "d3dx9.lib")   
  17.   
  18. // 定义的宏   
  19. #define JCLASSNAME  "优化的程序"   
  20. #define JCAPTION  "程序演示"   
  21. #define WINDOW_WIDTH 320   
  22. #define WINDOW_HEIGHT 320   
  23. #define FULLSCREEN  FALSE// 全屏非全屏的标识符   
  24. #define SAFE_RELEASE( p ) if ( p ) p->Release(); p = NULL;   
  25.   
  26. // 调整编译器设置   
  27. #pragma warning( disable: 4100 )   
  28.   
  29. #if FULLSCREEN     // 全屏非全屏的设置   
  30. #define WINDOW_STYLE WS_EX_TOPMOST | WS_POPUP | WS_VISIBLE   
  31. #else   
  32. #define WINDOW_STYLE WS_CAPTION | WS_SYSMENU   
  33. #endif   
  34.   
  35. /*----------------------------------------------------------------------------*/  
  36.   
  37. // 全局变量   
  38. LPDIRECT3D9 g_JD3D = NULL;// D3D结构体   
  39. LPDIRECT3DDEVICE9 g_JDevice = NULL;// D3D装置结构体   
  40. LPD3DXFONT g_FPSFont = NULL;// 指向FPS字体的指针   
  41. RECT g_FPSFontPos = { WINDOW_WIDTH - 100, WINDOW_HEIGHT - 15,    
  42. WINDOW_WIDTH, WINDOW_HEIGHT};// FPS所在的矩形框   
  43. INT g_FrameCount = 0;// 帧的计数器   
  44. INT g_lastTime = 0;// 记录上一秒的时间   
  45. INT g_currentTime = 0;// 记录当前的时间   
  46. CHAR g_FPSstr[25] = { 0 };// 记录当前帧率的字符串   
  47. IDirect3DSurface9* g_surface = NULL;// 平面的指针   
  48.   
  49. /*----------------------------------------------------------------------------*/  
  50. // 子图像和Alpha融合的头文件   
  51. #include "AlphaBlend.h"   
  52.   
  53. /*----------------------------------------------------------------------------*/  
  54. // 函数的声明   
  55. BOOL InitializeD3D( HWND hWnd )   
  56. {   
  57.  D3DDISPLAYMODE displayMode;   
  58.   
  59.  //创建D3D对象   
  60.  g_JD3D = Direct3DCreate9( D3D_SDK_VERSION );   
  61.  if ( g_JD3D == NULL )   
  62.   return FALSE;   
  63.   
  64.  // 获取显示器的模式   
  65.  if ( FAILED( g_JD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &displayMode ) ) )   
  66.   return FALSE;   
  67.   
  68.  // D3D显示的参数   
  69.  D3DPRESENT_PARAMETERS jd3dpp;   
  70.  ZeroMemory( &jd3dpp, sizeof( jd3dpp ) );   
  71.   
  72.  // 初始化D3DPRESENT_PARAMETERS   
  73.  jd3dpp.Windowed               = !FULLSCREEN;   
  74.  jd3dpp.BackBufferWidth    = WINDOW_WIDTH;   
  75.  jd3dpp.BackBufferHeight    = WINDOW_HEIGHT;   
  76.  jd3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;   
  77.  jd3dpp.BackBufferFormat       = displayMode.Format;   
  78.  jd3dpp.EnableAutoDepthStencil = TRUE;   
  79.  jd3dpp.AutoDepthStencilFormat = D3DFMT_D16;   
  80.   
  81.  // 创建设备   
  82.  if(FAILED( g_JD3D->CreateDevice( D3DADAPTER_DEFAULT,    
  83.   D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,    
  84.   &jd3dpp, &g_JDevice ) ) )   
  85.   return FALSE;   
  86.   
  87.  // 设置渲染状态   
  88.  g_JDevice->SetRenderState( D3DRS_LIGHTING, FALSE );   
  89.  g_JDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );   
  90.   
  91.  // 创建字体   
  92.  if ( FAILED( D3DXCreateFont( g_JDevice, 15, 0, 1, 1, 0, DEFAULT_CHARSET,   
  93.   OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,   
  94.   "Impact", &g_FPSFont ) ) ) return FALSE;   
  95.   
  96.  // 创建离屏平面   
  97.  if ( FAILED ( g_JDevice->CreateOffscreenPlainSurface( WINDOW_WIDTH, WINDOW_HEIGHT,   
  98.   D3DFMT_X8R8G8B8, // 平面格式   
  99.   D3DPOOL_DEFAULT, // 内存池格式   
  100.   &g_surface,        // 保存结果的缓存   
  101.   NULL) ) )        // 保留参数   
  102.   return FALSE;   
  103.   
  104.  // 载入背景平面图像   
  105.  if ( FAILED( D3DXLoadSurfaceFromFile( g_surface, NULL, NULL, "背景图案.tga",    
  106.   NULL, D3DX_DEFAULT, 0, NULL ) ) ) return FALSE;   
  107.   
  108.  // 初始化子图形   
  109.  if ( InitialSprite() == FALSE )   
  110.   return FALSE;   
  111.   
  112.  return TRUE;   
  113. }   
  114. /*----------------------------------------------------------------------------*/  
  115. // 释放所有资源   
  116. void ReleaseMemory( void )   
  117. {   
  118.  SAFE_RELEASE( g_JD3D );   
  119.  SAFE_RELEASE( g_JDevice );   
  120.  SAFE_RELEASE( g_FPSFont );   
  121.  SAFE_RELEASE( g_surface );   
  122.  AdditionalRelease();// 释放sprite和texture所占用的内存   
  123. }   
  124. /*----------------------------------------------------------------------------*/  
  125. // 渲染屏幕   
  126. void RenderScene( void )   
  127. {   
  128.  // 计数器开始计数(以毫秒计)   
  129.  g_currentTime = GetTickCount();   
  130.  if ( g_currentTime - g_lastTime > 1000 )   
  131.  {   
  132.   sprintf_s( g_FPSstr, 25, "当前FPS:%d", g_FrameCount );   
  133.   g_lastTime = g_currentTime;   
  134.   g_FrameCount = 0;   
  135.  }   
  136.  else g_FrameCount++;   
  137.   
  138.  g_JDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,    
  139.   D3DCOLOR_XRGB( 0, 0, 0), 1.0f, 0);// 清除屏幕   
  140.   
  141.  // 载入背景平面图像   
  142.  IDirect3DSurface9* backbuffer = NULL;   
  143.  g_JDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO,    
  144.   &backbuffer );// 获取后台缓存   
  145.  g_JDevice->StretchRect( g_surface, NULL,    
  146.   backbuffer, NULL, D3DTEXF_NONE );// 将后台矩形放入前景矩形   
  147.   
  148.  // 开始渲染   
  149.  g_JDevice->BeginScene();   
  150.   
  151.  RenderSprite();// 使用Alpha混合渲染子图形   
  152.   
  153.  g_FPSFont->DrawText( NULL, g_FPSstr, -1, &g_FPSFontPos, DT_CENTER,   
  154.   D3DCOLOR_XRGB( 0, 0, 0 ) );// 显示字体   
  155.   
  156.  // 结束渲染   
  157.  g_JDevice->EndScene();   
  158.   
  159.  g_JDevice->Present( NULL, NULL, NULL, NULL );   
  160. }   
  161. /*----------------------------------------------------------------------------*/  
  162. // 回调函数,用来处理消息   
  163. HRESULT CALLBACK MyAppProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )   
  164. {   
  165.  switch ( msg )   
  166.  {   
  167.  case WM_DESTROY:   
  168.   PostQuitMessage( 0 );   
  169.   return 0;   
  170.  case WM_KEYDOWN:   
  171.   if ( wParam == VK_ESCAPE ) PostQuitMessage( 0 );   
  172.   return 0;   
  173.  }   
  174.  return (HRESULT)DefWindowProc( hWnd, msg, wParam, lParam );   
  175. };   
  176. /*----------------------------------------------------------------------------*/  
  177. // 程序的入口,主函数   
  178. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmd, INT show )   
  179. {   
  180.  // 设置Window Class结构并且注册它   
  181.  WNDCLASSEX jWndCls = { sizeof( jWndCls ), CS_CLASSDC, MyAppProc, 0L, 0L, hInst,    
  182.   NULL, LoadCursor( NULL, IDC_ARROW) , 0, NULL, JCLASSNAME, NULL };   
  183.  RegisterClassEx( &jWndCls );   
  184.   
  185.  // 设置窗口并且显示窗口   
  186.  HWND hWnd = CreateWindow( JCLASSNAME, JCAPTION, WINDOW_STYLE, 100, 40,   
  187.   WINDOW_WIDTH, WINDOW_HEIGHT, GetDesktopWindow(), NULL, jWndCls.hInstance, NULL);   
  188.  if ( hWnd == NULL )   
  189.   return FALSE;   
  190.  ShowWindow( hWnd, SW_SHOWDEFAULT );   
  191.  UpdateWindow( hWnd );   
  192.   
  193.  // 初始化设置   
  194.  if ( InitializeD3D( hWnd ) == FALSE )   
  195.   return FALSE;   
  196.   
  197.  // 进入消息循环   
  198.  MSG msg;   
  199.  ZeroMemory( &msg, sizeof( msg ) );   
  200.  while( msg.message != WM_QUIT )   
  201.  {   
  202.   if ( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )   
  203.   {   
  204.    TranslateMessage( &msg );   
  205.    DispatchMessage( &msg );   
  206.   }   
  207.   else  
  208.   {   
  209.    // 渲染屏幕   
  210.    RenderScene();   
  211.   }   
  212.  }   
  213.   
  214.  // 程序结束,释放内存所有资源   
  215.  ReleaseMemory();   
  216.   
  217.  // 解除窗口注册   
  218.  UnregisterClass( JCLASSNAME, jWndCls.hInstance );   
  219.  return ( INT ) msg.wParam;   
  220. }  

 下面就是我的AlphaBlend.h文件的内容:

Code:
  1. /*---------------------------------------------------------------------------  
  2. 蒋轶民制作 E-mail:jiangcaiyang123@163.com  
  3. 文件名:AlphaBlend.cpp  
  4. 作用:载入子图像和Alpha融合  
  5. ----------------------------------------------------------------------------*/  
  6. /*--------------------------------------------------------------------------*/  
  7. // 条件编译   
  8. #ifndef _ALPHABLEND_H_   
  9. #define _ALPHABLEND_H_   
  10.   
  11. // 定义的宏   
  12. #define SPRITE_WIDTH 120   
  13. #define SPRITE_HEIGHT 164   
  14.   
  15. /*----------------------------------------------------------------------------*/  
  16. // 全局变量   
  17. LPD3DXSPRITE g_Sprite = NULL;// 指向sprite结构的指针   
  18. LPDIRECT3DTEXTURE9 g_Texture = NULL;// 指向纹理的指针   
  19.   
  20. /*----------------------------------------------------------------------------*/  
  21. // 初始化子图形   
  22. bool InitialSprite( void )   
  23. {   
  24.  // 载入纹理图像并使用双线性滤波   
  25.  if ( FAILED ( D3DXCreateTextureFromFileEx( g_JDevice, "POP_Sprite.tga",   
  26.   SPRITE_WIDTH, // 我不得不手动设置。D3DPOOL_DEFAULT在纹理中起作用,但是应用在D3DXSPRITE中会产生问题。   
  27.   SPRITE_HEIGHT, // 我不得不手动设置。D3DPOOL_DEFAULT在纹理中起作用,但是应用在D3DXSPRITE中会产生问题。   
  28.   1,   // 不要创建mip-map。它在子图形动画中会抛弃像素数学计算   
  29.   D3DPOOL_DEFAULT,   
  30.   D3DFMT_UNKNOWN,   
  31.   D3DPOOL_DEFAULT,   
  32.   D3DX_DEFAULT,   
  33.   D3DX_DEFAULT,   
  34.   D3DCOLOR_XRGB( 0, 0, 0),   
  35.   NULL,   
  36.   NULL,   
  37.   &g_Texture ) ) )   
  38.   return false;   
  39.  g_JDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );   
  40.  g_JDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );   
  41.   
  42.  // 设置三角形的背面不被剔除   
  43.  g_JDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );   
  44.   
  45.  // 创建子图形   
  46.  if ( FAILED( D3DXCreateSprite( g_JDevice, &g_Sprite ) ) )   
  47.   return false;   
  48.   
  49.  return true;   
  50. }   
  51.   
  52. /*----------------------------------------------------------------------------*/  
  53. // 使用Alpha混合渲染子图形   
  54. void RenderSprite( void )   
  55. {   
  56.  // 设置静态变量,以便迭代而多次不初始化。它相当于全局变量   
  57.  static float fPosition = 0.0f;   
  58.   
  59.  // 设置D3DXVECTOR3结构体,在D3DXSPRITE::Draw函数中有应用   
  60.  D3DXVECTOR3 vCenter( 0.0f, 0.0f, 0.0f );   
  61.  D3DXVECTOR3 vPosition( fPosition, 150.0f, 0.0f );   
  62.   
  63.  // 渲染Sprite   
  64.  g_Sprite->Begin( D3DXSPRITE_ALPHABLEND );// 以Alpha混合形式进行渲染   
  65.  g_Sprite->Draw( g_Texture, NULL, &vCenter, &vPosition,   
  66.   D3DCOLOR_XRGB( 255, 255, 255 ) );   
  67.  g_Sprite->End();// 结束渲染   
  68.  if ( fPosition++ > WINDOW_WIDTH )// 检测越界   
  69.   fPosition = 0.0f - SPRITE_WIDTH;   
  70. }   
  71.   
  72. /*----------------------------------------------------------------------------*/  
  73. // 释放sprite和texture所占用的内存   
  74. void AdditionalRelease( void )   
  75. {   
  76.  SAFE_RELEASE( g_Sprite );   
  77.  SAFE_RELEASE( g_Texture );   
  78. }   
  79. #endif  

 我使用的tga格式展示给大家看看。其中sprite纹理的宽和高分别是120×164。

 程序的演示效果如下:

我更多的DirectX程序,请看:

 为DirectX游戏计算帧率

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

 为自己创作一个好的DirectX程序风

 

我的游戏:走迷宫(DirectX版) 

 如果大家有什么问题的话,可以回复我啊。