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

使用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. #include<windows.h>
  9. #include<d3d9.h>
  10. #include<d3dx9.h>
  11. #include<stdio.h>
  12. //库文件
  13. #pragmacomment(lib,"d3d9.lib")
  14. #pragmacomment(lib,"d3dx9.lib")
  15. //定义的宏
  16. #defineJCLASSNAME"优化的程序"
  17. #defineJCAPTION"程序演示"
  18. #defineWINDOW_WIDTH320
  19. #defineWINDOW_HEIGHT320
  20. #defineFULLSCREENFALSE//全屏非全屏的标识符
  21. #defineSAFE_RELEASE(p)if(p)p->Release();p=NULL;
  22. //调整编译器设置
  23. #pragmawarning(disable:4100)
  24. #ifFULLSCREEN//全屏非全屏的设置
  25. #defineWINDOW_STYLEWS_EX_TOPMOST|WS_POPUP|WS_VISIBLE
  26. #else
  27. #defineWINDOW_STYLEWS_CAPTION|WS_SYSMENU
  28. #endif
  29. /*----------------------------------------------------------------------------*/
  30. //全局变量
  31. LPDIRECT3D9g_JD3D=NULL;//D3D结构体
  32. LPDIRECT3DDEVICE9g_JDevice=NULL;//D3D装置结构体
  33. LPD3DXFONTg_FPSFont=NULL;//指向FPS字体的指针
  34. RECTg_FPSFontPos={WINDOW_WIDTH-100,WINDOW_HEIGHT-15,
  35. WINDOW_WIDTH,WINDOW_HEIGHT};//FPS所在的矩形框
  36. INTg_FrameCount=0;//帧的计数器
  37. INTg_lastTime=0;//记录上一秒的时间
  38. INTg_currentTime=0;//记录当前的时间
  39. CHARg_FPSstr[25]={0};//记录当前帧率的字符串
  40. IDirect3DSurface9*g_surface=NULL;//平面的指针
  41. /*----------------------------------------------------------------------------*/
  42. //子图像和Alpha融合的头文件
  43. #include"AlphaBlend.h"
  44. /*----------------------------------------------------------------------------*/
  45. //函数的声明
  46. BOOLInitializeD3D(HWNDhWnd)
  47. {
  48. D3DDISPLAYMODEdisplayMode;
  49. //创建D3D对象
  50. g_JD3D=Direct3DCreate9(D3D_SDK_VERSION);
  51. if(g_JD3D==NULL)
  52. returnFALSE;
  53. //获取显示器的模式
  54. if(FAILED(g_JD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&displayMode)))
  55. returnFALSE;
  56. //D3D显示的参数
  57. D3DPRESENT_PARAMETERSjd3dpp;
  58. ZeroMemory(&jd3dpp,sizeof(jd3dpp));
  59. //初始化D3DPRESENT_PARAMETERS
  60. jd3dpp.Windowed=!FULLSCREEN;
  61. jd3dpp.BackBufferWidth=WINDOW_WIDTH;
  62. jd3dpp.BackBufferHeight=WINDOW_HEIGHT;
  63. jd3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
  64. jd3dpp.BackBufferFormat=displayMode.Format;
  65. jd3dpp.EnableAutoDepthStencil=TRUE;
  66. jd3dpp.AutoDepthStencilFormat=D3DFMT_D16;
  67. //创建设备
  68. if(FAILED(g_JD3D->CreateDevice(D3DADAPTER_DEFAULT,
  69. D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,
  70. &jd3dpp,&g_JDevice)))
  71. returnFALSE;
  72. //设置渲染状态
  73. g_JDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
  74. g_JDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE);
  75. //创建字体
  76. if(FAILED(D3DXCreateFont(g_JDevice,15,0,1,1,0,DEFAULT_CHARSET,
  77. OUT_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,
  78. "Impact",&g_FPSFont)))returnFALSE;
  79. //创建离屏平面
  80. if(FAILED(g_JDevice->CreateOffscreenPlainSurface(WINDOW_WIDTH,WINDOW_HEIGHT,
  81. D3DFMT_X8R8G8B8,//平面格式
  82. D3DPOOL_DEFAULT,//内存池格式
  83. &g_surface,//保存结果的缓存
  84. NULL)))//保留参数
  85. returnFALSE;
  86. //载入背景平面图像
  87. if(FAILED(D3DXLoadSurfaceFromFile(g_surface,NULL,NULL,"背景图案.tga",
  88. NULL,D3DX_DEFAULT,0,NULL)))returnFALSE;
  89. //初始化子图形
  90. if(InitialSprite()==FALSE)
  91. returnFALSE;
  92. returnTRUE;
  93. }
  94. /*----------------------------------------------------------------------------*/
  95. //释放所有资源
  96. voidReleaseMemory(void)
  97. {
  98. SAFE_RELEASE(g_JD3D);
  99. SAFE_RELEASE(g_JDevice);
  100. SAFE_RELEASE(g_FPSFont);
  101. SAFE_RELEASE(g_surface);
  102. AdditionalRelease();//释放sprite和texture所占用的内存
  103. }
  104. /*----------------------------------------------------------------------------*/
  105. //渲染屏幕
  106. voidRenderScene(void)
  107. {
  108. //计数器开始计数(以毫秒计)
  109. g_currentTime=GetTickCount();
  110. if(g_currentTime-g_lastTime>1000)
  111. {
  112. sprintf_s(g_FPSstr,25,"当前FPS:%d",g_FrameCount);
  113. g_lastTime=g_currentTime;
  114. g_FrameCount=0;
  115. }
  116. elseg_FrameCount++;
  117. g_JDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
  118. D3DCOLOR_XRGB(0,0,0),1.0f,0);//清除屏幕
  119. //载入背景平面图像
  120. IDirect3DSurface9*backbuffer=NULL;
  121. g_JDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,
  122. &backbuffer);//获取后台缓存
  123. g_JDevice->StretchRect(g_surface,NULL,
  124. backbuffer,NULL,D3DTEXF_NONE);//将后台矩形放入前景矩形
  125. //开始渲染
  126. g_JDevice->BeginScene();
  127. RenderSprite();//使用Alpha混合渲染子图形
  128. g_FPSFont->DrawText(NULL,g_FPSstr,-1,&g_FPSFontPos,DT_CENTER,
  129. D3DCOLOR_XRGB(0,0,0));//显示字体
  130. //结束渲染
  131. g_JDevice->EndScene();
  132. g_JDevice->Present(NULL,NULL,NULL,NULL);
  133. }
  134. /*----------------------------------------------------------------------------*/
  135. //回调函数,用来处理消息
  136. HRESULTCALLBACKMyAppProc(HWNDhWnd,UINTmsg,WPARAMwParam,LPARAMlParam)
  137. {
  138. switch(msg)
  139. {
  140. caseWM_DESTROY:
  141. PostQuitMessage(0);
  142. return0;
  143. caseWM_KEYDOWN:
  144. if(wParam==VK_ESCAPE)PostQuitMessage(0);
  145. return0;
  146. }
  147. return(HRESULT)DefWindowProc(hWnd,msg,wParam,lParam);
  148. };
  149. /*----------------------------------------------------------------------------*/
  150. //程序的入口,主函数
  151. INTWINAPIWinMain(HINSTANCEhInst,HINSTANCEhPrevInst,LPSTRcmd,INTshow)
  152. {
  153. //设置WindowClass结构并且注册它
  154. WNDCLASSEXjWndCls={sizeof(jWndCls),CS_CLASSDC,MyAppProc,0L,0L,hInst,
  155. NULL,LoadCursor(NULL,IDC_ARROW),0,NULL,JCLASSNAME,NULL};
  156. RegisterClassEx(&jWndCls);
  157. //设置窗口并且显示窗口
  158. HWNDhWnd=CreateWindow(JCLASSNAME,JCAPTION,WINDOW_STYLE,100,40,
  159. WINDOW_WIDTH,WINDOW_HEIGHT,GetDesktopWindow(),NULL,jWndCls.hInstance,NULL);
  160. if(hWnd==NULL)
  161. returnFALSE;
  162. ShowWindow(hWnd,SW_SHOWDEFAULT);
  163. UpdateWindow(hWnd);
  164. //初始化设置
  165. if(InitializeD3D(hWnd)==FALSE)
  166. returnFALSE;
  167. //进入消息循环
  168. MSGmsg;
  169. ZeroMemory(&msg,sizeof(msg));
  170. while(msg.message!=WM_QUIT)
  171. {
  172. if(PeekMessage(&msg,NULL,0U,0U,PM_REMOVE))
  173. {
  174. TranslateMessage(&msg);
  175. DispatchMessage(&msg);
  176. }
  177. else
  178. {
  179. //渲染屏幕
  180. RenderScene();
  181. }
  182. }
  183. //程序结束,释放内存所有资源
  184. ReleaseMemory();
  185. //解除窗口注册
  186. UnregisterClass(JCLASSNAME,jWndCls.hInstance);
  187. return(INT)msg.wParam;
  188. }

下面就是我的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. #defineSPRITE_WIDTH120
  12. #defineSPRITE_HEIGHT164
  13. /*----------------------------------------------------------------------------*/
  14. //全局变量
  15. LPD3DXSPRITEg_Sprite=NULL;//指向sprite结构的指针
  16. LPDIRECT3DTEXTURE9g_Texture=NULL;//指向纹理的指针
  17. /*----------------------------------------------------------------------------*/
  18. //初始化子图形
  19. boolInitialSprite(void)
  20. {
  21. //载入纹理图像并使用双线性滤波
  22. if(FAILED(D3DXCreateTextureFromFileEx(g_JDevice,"POP_Sprite.tga",
  23. SPRITE_WIDTH,//我不得不手动设置。D3DPOOL_DEFAULT在纹理中起作用,但是应用在D3DXSPRITE中会产生问题。
  24. SPRITE_HEIGHT,//我不得不手动设置。D3DPOOL_DEFAULT在纹理中起作用,但是应用在D3DXSPRITE中会产生问题。
  25. 1,//不要创建mip-map。它在子图形动画中会抛弃像素数学计算
  26. D3DPOOL_DEFAULT,
  27. D3DFMT_UNKNOWN,
  28. D3DPOOL_DEFAULT,
  29. D3DX_DEFAULT,
  30. D3DX_DEFAULT,
  31. D3DCOLOR_XRGB(0,0,0),
  32. NULL,
  33. NULL,
  34. &g_Texture)))
  35. returnfalse;
  36. g_JDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
  37. g_JDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
  38. //设置三角形的背面不被剔除
  39. g_JDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
  40. //创建子图形
  41. if(FAILED(D3DXCreateSprite(g_JDevice,&g_Sprite)))
  42. returnfalse;
  43. returntrue;
  44. }
  45. /*----------------------------------------------------------------------------*/
  46. //使用Alpha混合渲染子图形
  47. voidRenderSprite(void)
  48. {
  49. //设置静态变量,以便迭代而多次不初始化。它相当于全局变量
  50. staticfloatfPosition=0.0f;
  51. //设置D3DXVECTOR3结构体,在D3DXSPRITE::Draw函数中有应用
  52. D3DXVECTOR3vCenter(0.0f,0.0f,0.0f);
  53. D3DXVECTOR3vPosition(fPosition,150.0f,0.0f);
  54. //渲染Sprite
  55. g_Sprite->Begin(D3DXSPRITE_ALPHABLEND);//以Alpha混合形式进行渲染
  56. g_Sprite->Draw(g_Texture,NULL,&vCenter,&vPosition,
  57. D3DCOLOR_XRGB(255,255,255));
  58. g_Sprite->End();//结束渲染
  59. if(fPosition++>WINDOW_WIDTH)//检测越界
  60. fPosition=0.0f-SPRITE_WIDTH;
  61. }
  62. /*----------------------------------------------------------------------------*/
  63. //释放sprite和texture所占用的内存
  64. voidAdditionalRelease(void)
  65. {
  66. SAFE_RELEASE(g_Sprite);
  67. SAFE_RELEASE(g_Texture);
  68. }
  69. #endif

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

程序的演示效果如下:

我更多的DirectX程序,请看:

为DirectX游戏计算帧率

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

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值