用DirectX设计游戏主角运动

用DirectX设计游戏主角运动


 今天工作了一整天,就是在弄这个。DirectX的强大之处多得是,只要你肯发掘。像今天我就弄了一个让主角运动的程序,自己还制作了动画呢。画得不好请见谅啊。
 程序呢,就是将sprite类简单地封装了一下,变得更加易用。但是遗憾的是,我还没有实现主角的跳跃。怎么办呢?只好再奋斗一天了。
 程序是载入八个图像,然后每次显示不同的图像,这样主角的运动就显示出来啦。这就是我动画的奥秘。虽然这个类还有些成员函数是空的,但是总体来说,我对这个自己编写的类还是满意的。因为它有点继承了DIrectX库的特点,这样也比较易用。我会以这个程序为经验,下次开发出更好的程序的。
 

 

 这是我的PlayerAction.h文件。

Code:
  1. /*---------------------------------------------------------------------------  
  2. 蒋轶民制作 E-mail:jiangcaiyang123@163.com  
  3. 文件名:PlayerAction.h  
  4. 作用:让主角运动的实现  
  5. ----------------------------------------------------------------------------*/  
  6. /*--------------------------------------------------------------------------*/  
  7. // 条件编译   
  8. #ifndef _PLAYERACTION_H_   
  9. #define _PLAYERACTION_H_   
  10.   
  11. // 定义的宏   
  12. #define SPRITE_WIDTH 50   
  13. #define SPRITE_HEIGHT 50   
  14.   
  15. // 将主角这个类封装起来   
  16. class JPlayer   
  17. {   
  18. public:   
  19.  JPlayer():xPos(WINDOW_WIDTH*0.5f),yPos(WINDOW_HEIGHT-100),   
  20.   pPlayerSprite(0),pPlayerTexture(0)   
  21.  { spriteRect.top = 0; }//默认构造函数   
  22.  ~JPlayer(){}// 默认析构函数   
  23.  bool Initialize( void );// 初始化主角   
  24.  bool GoLeft( void );// 向左走   
  25.  bool GoRight( void );// 向右走   
  26.  bool Jump( void );// 跳跃   
  27.  bool Display( void );// 显示主角   
  28.  void Release( void );// 释放空间   
  29. private:   
  30.  float xPos, yPos;// 主角的横纵坐标的位置   
  31.  RECT spriteRect;// 精灵动画的矩形框   
  32.  LPD3DXSPRITE pPlayerSprite;// 主角的子图形指针   
  33.  LPDIRECT3DTEXTURE9 pPlayerTexture;// 主角的图像纹理指针   
  34. };   
  35. typedef JPlayer* LPJPLAYER;// 定义主角的指针类型   
  36.   
  37. /*--------------------------------------------------------------------------*/  
  38. // 初始化主角   
  39. bool JPlayer::Initialize( void )   
  40. {   
  41.  // 载入纹理图像并使用双线性滤波   
  42.  if ( FAILED ( D3DXCreateTextureFromFileEx( g_JDevice, "蘑菇(合图).png",   
  43.   200, // 我不得不手动设置。D3DPOOL_DEFAULT在纹理中起作用,但是应用在D3DXSPRITE中会产生问题。   
  44.   100, // 我不得不手动设置。D3DPOOL_DEFAULT在纹理中起作用,但是应用在D3DXSPRITE中会产生问题。   
  45.   1,   // 不要创建mip-map。它在子图形动画中会抛弃像素数学计算   
  46.   D3DPOOL_DEFAULT,   
  47.   D3DFMT_UNKNOWN,   
  48.   D3DPOOL_DEFAULT,   
  49.   D3DX_DEFAULT,   
  50.   D3DX_DEFAULT,   
  51.   D3DCOLOR_XRGB( 0, 0, 0 ),   
  52.   NULL,   
  53.   NULL,   
  54.   &pPlayerTexture ) ) )   
  55.   return false;   
  56.  g_JDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );   
  57.  g_JDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );   
  58.   
  59.  // 设置三角形的背面不被剔除   
  60.  g_JDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );   
  61.   
  62.  // 创建子图形   
  63.  if ( FAILED( D3DXCreateSprite( g_JDevice, &pPlayerSprite ) ) )   
  64.   return false;   
  65.   
  66.  return true;   
  67. }   
  68. /*--------------------------------------------------------------------------*/  
  69. // 向左走   
  70. bool JPlayer::GoLeft( void )   
  71. {   
  72.  xPos -= 4.0f;   
  73.  spriteRect.top = 0;   
  74.  return true;   
  75. }   
  76. /*--------------------------------------------------------------------------*/  
  77. // 向右走   
  78. bool JPlayer::GoRight( void )   
  79. {   
  80.  xPos += 4.0f;   
  81.  spriteRect.top = 50;   
  82.  return true;   
  83. }   
  84. /*--------------------------------------------------------------------------*/  
  85. // 跳跃   
  86. bool JPlayer::Jump( void )   
  87. {   
  88.  return true;   
  89. }   
  90. /*--------------------------------------------------------------------------*/  
  91. // 显示主角   
  92. bool JPlayer::Display( void )   
  93. {   
  94.  // 碰撞检测   
  95.  if ( xPos < 0.0f )   
  96.   xPos = 0.0f;   
  97.  else if ( xPos > WINDOW_WIDTH - SPRITE_WIDTH )   
  98.   xPos = WINDOW_WIDTH - SPRITE_WIDTH;    
  99.   
  100.  // 显示每一个子图形   
  101.  static float frame = 0;   
  102.  spriteRect.left = (long)floor( frame ) * 50;   
  103.  spriteRect.bottom = spriteRect.top + 50;   
  104.  spriteRect.right = spriteRect.left + 50;   
  105.  frame += 0.05f;   
  106.  if ( frame >= 4.0f ) frame = 0.0f;   
  107.   
  108.  // 设置D3DXVECTOR3结构体,在D3DXSPRITE::Draw函数中有应用   
  109.  D3DXVECTOR3 vCenter( 0.0f, 0.0f, 0.0f );   
  110.  D3DXVECTOR3 vPosition( xPos, yPos, 0.0f );   
  111.   
  112.  // 渲染Sprite   
  113.  pPlayerSprite->Begin( D3DXSPRITE_ALPHABLEND );// 以Alpha混合形式进行渲染   
  114.  pPlayerSprite->Draw( pPlayerTexture, &spriteRect, &vCenter, &vPosition,   
  115.   D3DCOLOR_XRGB( 255, 255, 255 ) );   
  116.  pPlayerSprite->End();// 结束渲染   
  117.  return true;   
  118. }   
  119. /*--------------------------------------------------------------------------*/  
  120. // 释放空间   
  121. void JPlayer::Release( void )   
  122. {   
  123.  if ( pPlayerSprite ) pPlayerSprite->Release(); pPlayerSprite = NULL;   
  124.  if ( pPlayerTexture ) pPlayerTexture->Release(); pPlayerTexture = NULL;   
  125. }   
  126. /*--------------------------------------------------------------------------*/  
  127.   
  128. #endif  


 下面是我的MainFrame.h文件:

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

 程序需要载入背景图和纹理图,分别如下:

 程序的动态显示如下:

我的更多DirectX文章:

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

 为DirectX游戏计算帧率

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

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

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

 怎么样?这个和我心目中的游戏还差得远呢。以后要做比这个更加强大的游戏!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值