使用DirectX让子图形移动(精灵动画)

使用DirectX让子图形移动(精灵动画)
这是我今天从这本书上学的,这本书的名字叫做《Beginning DirectX9》这本书是英文的。好在我还看得懂英文。书上给了很多DirectX编程的初学者怎样进行DirectX编程。今天我看到了Sprite(子图形,又叫精灵图形)这一章,这一章讲了怎样使用DirectX进行精灵图形的绘制。书上的内容还是比较通俗易懂的。但是有一个缺陷,就是没有那位高人有这本书的光碟。所以我们国内的读者只好看pdf文件了。我在研究这本书的时候好在有些基础,要不然在4个月前,我根本就不知道怎样对书上的错误进行更正。正如我上面所说,书还是有很多缺陷的。这就要我们读者进行更正喽。在今天一个多小时的努力和我的基本框架的基础上,我终于把书上要显示的效果实现了。下面就是我的代码,注释是我翻译和添加的,很好懂。如果还是不懂的话,可以单独地问我或是跟帖,我会耐心地回答大家的问题的。

首先是我的MainFrame.cpp文件。

Code:
  1. /*---------------------------------------------------------------------------
  2. 蒋轶民制作E-mail:jiangcaiyang123@163.com
  3. 文件名:MainFrame.cpp
  4. 作用:载入子图像(sprite)
  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_WIDTH640
  19. #defineWINDOW_HEIGHT480
  20. #defineFULLSCREENFALSE//全屏与否的开关
  21. #defineSAVE_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. /*----------------------------------------------------------------------------*/
  41. //初始化子图形的头文件
  42. #include"Sprite.h"
  43. /*----------------------------------------------------------------------------*/
  44. //函数的声明
  45. BOOLInitializeD3D(HWNDhWnd)
  46. {
  47. D3DDISPLAYMODEdisplayMode;
  48. //创建D3D对象
  49. g_JD3D=Direct3DCreate9(D3D_SDK_VERSION);
  50. if(g_JD3D==NULL)
  51. returnFALSE;
  52. //获取显示器的模式
  53. if(FAILED(g_JD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&displayMode)))
  54. returnFALSE;
  55. //D3D显示的参数
  56. D3DPRESENT_PARAMETERSjd3dpp;
  57. ZeroMemory(&jd3dpp,sizeof(jd3dpp));
  58. //初始化D3DPRESENT_PARAMETERS
  59. jd3dpp.Windowed=!FULLSCREEN;
  60. jd3dpp.BackBufferWidth=WINDOW_WIDTH;
  61. jd3dpp.BackBufferHeight=WINDOW_HEIGHT;
  62. jd3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
  63. jd3dpp.BackBufferFormat=displayMode.Format;
  64. jd3dpp.EnableAutoDepthStencil=TRUE;
  65. jd3dpp.AutoDepthStencilFormat=D3DFMT_D16;
  66. //创建设备
  67. if(FAILED(g_JD3D->CreateDevice(D3DADAPTER_DEFAULT,
  68. D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,
  69. &jd3dpp,&g_JDevice)))
  70. returnFALSE;
  71. //设置渲染状态
  72. g_JDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
  73. g_JDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE);
  74. //创建字体
  75. if(FAILED(D3DXCreateFont(g_JDevice,15,0,1,1,0,DEFAULT_CHARSET,
  76. OUT_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,
  77. "Impact",&g_FPSFont)))returnFALSE;
  78. if(InitSprites()==FALSE)
  79. returnFALSE;
  80. returnTRUE;
  81. }
  82. /*----------------------------------------------------------------------------*/
  83. //释放所有资源
  84. voidReleaseMemory(void)
  85. {
  86. SAVE_RELEASE(g_JD3D);
  87. SAVE_RELEASE(g_JDevice);
  88. SAVE_RELEASE(g_FPSFont);
  89. }
  90. /*----------------------------------------------------------------------------*/
  91. //渲染屏幕
  92. voidRenderScene(void)
  93. {
  94. //计数器开始计数(以毫秒计)
  95. g_currentTime=GetTickCount();
  96. if(g_currentTime-g_lastTime>1000)
  97. {
  98. sprintf_s(g_FPSstr,25,"当前FPS:%d",g_FrameCount);
  99. g_lastTime=g_currentTime;
  100. g_FrameCount=0;
  101. }
  102. elseg_FrameCount++;
  103. g_JDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
  104. D3DCOLOR_XRGB(179,221,247),1.0f,0);//清除屏幕
  105. //渲染子图形
  106. RenderSprite();
  107. //开始渲染
  108. g_JDevice->BeginScene();
  109. g_FPSFont->DrawText(NULL,g_FPSstr,-1,&g_FPSFontPos,DT_CENTER,
  110. D3DCOLOR_XRGB(255,255,255));//显示字体
  111. //结束渲染
  112. g_JDevice->EndScene();
  113. g_JDevice->Present(NULL,NULL,NULL,NULL);
  114. }
  115. /*----------------------------------------------------------------------------*/
  116. //回调函数,用来处理消息
  117. HRESULTCALLBACKMyAppProc(HWNDhWnd,UINTmsg,WPARAMwParam,LPARAMlParam)
  118. {
  119. switch(msg)
  120. {
  121. caseWM_DESTROY:
  122. PostQuitMessage(0);
  123. return0;
  124. caseWM_KEYDOWN:
  125. if(wParam==VK_ESCAPE)PostQuitMessage(0);
  126. return0;
  127. }
  128. return(HRESULT)DefWindowProc(hWnd,msg,wParam,lParam);
  129. };
  130. /*----------------------------------------------------------------------------*/
  131. //程序的入口,主函数
  132. INTWINAPIWinMain(HINSTANCEhInst,HINSTANCEhPrevInst,LPSTRcmd,INTshow)
  133. {
  134. //设置WindowClass结构并且注册它
  135. WNDCLASSEXjWndCls={sizeof(jWndCls),CS_CLASSDC,MyAppProc,0L,0L,hInst,
  136. NULL,LoadCursor(NULL,IDC_ARROW),0,NULL,JCLASSNAME,NULL};
  137. RegisterClassEx(&jWndCls);
  138. //设置窗口并且显示窗口
  139. HWNDhWnd=CreateWindow(JCLASSNAME,JCAPTION,WINDOW_STYLE,100,40,
  140. WINDOW_WIDTH,WINDOW_HEIGHT,GetDesktopWindow(),NULL,jWndCls.hInstance,NULL);
  141. if(hWnd==NULL)
  142. returnFALSE;
  143. ShowWindow(hWnd,SW_SHOWDEFAULT);
  144. UpdateWindow(hWnd);
  145. //初始化设置
  146. if(InitializeD3D(hWnd)==FALSE)
  147. returnFALSE;
  148. //进入消息循环
  149. MSGmsg;
  150. ZeroMemory(&msg,sizeof(msg));
  151. while(msg.message!=WM_QUIT)
  152. {
  153. if(PeekMessage(&msg,NULL,0U,0U,PM_REMOVE))
  154. {
  155. TranslateMessage(&msg);
  156. DispatchMessage(&msg);
  157. }
  158. else
  159. {
  160. //渲染屏幕
  161. RenderScene();
  162. }
  163. }
  164. //程序结束,释放内存所有资源
  165. ReleaseMemory();
  166. //解除窗口注册
  167. UnregisterClass(JCLASSNAME,jWndCls.hInstance);
  168. return(INT)msg.wParam;
  169. }

然后就是我的Sprite.h文件:

Code:
  1. /*---------------------------------------------------------------------------
  2. 蒋轶民制作E-mail:jiangcaiyang123@163.com
  3. 文件名:Sprite.h
  4. 作用:载入子图像(sprite)
  5. ----------------------------------------------------------------------------*/
  6. //预编译
  7. #ifndef_SPRITE_H_
  8. #define_SPRITE_H_
  9. /*----------------------------------------------------------------------------*/
  10. //头文件
  11. #include<time.h>
  12. /*----------------------------------------------------------------------------*/
  13. //定义与子图形有关的宏
  14. #defineSPRITE_WIDTH48
  15. #defineSPRITE_HEIGHT48
  16. #defineSCRN_WIDTHWINDOW_WIDTH
  17. #defineSCRN_HEIGHTWINDOW_HEIGHT
  18. /*----------------------------------------------------------------------------*/
  19. //自定义子图形的结构体
  20. structstSprite
  21. {
  22. stSprite():moveX(1),moveY(1){}//默认构造函数
  23. RECTsrcRect;//位置
  24. intposX;//X坐标
  25. intposY;//Y坐标
  26. intmoveX;//指定了一次性走多少个X像素
  27. intmoveY;//指定了一次性走多少个Y像素
  28. }spriteStruct[10];
  29. /*----------------------------------------------------------------------------*/
  30. //全局变量
  31. IDirect3DSurface9*surface;//平面的指针
  32. /*----------------------------------------------------------------------------*/
  33. //初始化子图形
  34. boolInitSprites(void)
  35. {
  36. //创建离屏平面用来显示图形
  37. if(FAILED(g_JDevice->CreateOffscreenPlainSurface(480,
  38. 48,
  39. D3DFMT_X8R8G8B8,
  40. D3DPOOL_DEFAULT,
  41. &surface,
  42. NULL)))returnfalse;
  43. //装载子图形
  44. if(FAILED(D3DXLoadSurfaceFromFile(surface,NULL,NULL,
  45. "sprite.tga",NULL,D3DX_DEFAULT,0,NULL)))returnfalse;
  46. inti;
  47. srand((unsignedint)time(NULL));//产生随机数
  48. //初始化10个子图形
  49. for(i=0;i<10;i++)
  50. {
  51. spriteStruct[i].srcRect.top=0;
  52. spriteStruct[i].srcRect.left=i*SPRITE_WIDTH;
  53. spriteStruct[i].srcRect.right=spriteStruct[i].srcRect.left+SPRITE_WIDTH;
  54. spriteStruct[i].srcRect.bottom=SPRITE_HEIGHT;
  55. spriteStruct[i].posX = abs( rand()%SCRN_WIDTH - SPRITE_WIDTH );
    spriteStruct[i].posY = abs( rand()%SCRN_HEIGHT - SPRITE_HEIGHT );
  56. }
  57. returntrue;
  58. }
  59. /*----------------------------------------------------------------------------*/
  60. //渲染子图形
  61. voidRenderSprite(void)
  62. {
  63. IDirect3DSurface9*backbuffer=NULL;
  64. inti;
  65. //调入后台缓存
  66. g_JDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&backbuffer);
  67. //循环显示子图形
  68. for(i=0;i<10;i++)
  69. {
  70. RECTdestRect;//创建一个临时的ERCT,用来迭代
  71. //填充每个子图形的数据
  72. destRect.left=spriteStruct[i].posX;
  73. destRect.top=spriteStruct[i].posY;
  74. destRect.bottom=destRect.top+SPRITE_HEIGHT;
  75. destRect.right=destRect.left+SPRITE_WIDTH;
  76. //改变子图形的X坐标,让其运动
  77. spriteStruct[i].posX+=spriteStruct[i].moveX;
  78. //检查X坐标是否超过了屏幕像素640
  79. if(spriteStruct[i].posX>=SCRN_WIDTH-SPRITE_WIDTH)
  80. {
  81. //如果像素超过了640,将每次运动的像素取相反数,这样就实现了反走
  82. spriteStruct[i].moveX*=-1;
  83. }
  84. //改变图形的Y坐标
  85. spriteStruct[i].posY+=spriteStruct[i].moveY;
  86. //检测Y坐标是否超过了屏幕像素480
  87. if(spriteStruct[i].posY>=SCRN_HEIGHT-SPRITE_HEIGHT)
  88. {
  89. //如果像素超过了480,将每次运动的像素取相反数,这样就实现了反走
  90. spriteStruct[i].moveY*=-1;
  91. }
  92. //如果子图形反走过头了,我们也必须限制其超过屏幕左边和上边
  93. if(spriteStruct[i].posX<=0)
  94. {
  95. //如果X坐标小于0,我们必须让其继续反走
  96. spriteStruct[i].moveX*=-1;
  97. }
  98. //检查子图形是否走到了屏幕的最上方
  99. if(spriteStruct[i].posY<=0)
  100. {
  101. //如果Y坐标小于0,我们必须让其继续反走
  102. spriteStruct[i].moveY*=-1;
  103. }
  104. //将子图形绘制在后台缓存上
  105. g_JDevice->StretchRect(surface,
  106. &spriteStruct[i].srcRect,
  107. backbuffer,
  108. &destRect,
  109. D3DTEXF_NONE);
  110. }
  111. }
  112. /*----------------------------------------------------------------------------*/
  113. #endif

载入的sprite.tga图片如右所示:

程序的效果如下图所示:


这次就写到这里了,如果大家有疑问的话,可以回复我哦。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值