ID3DXSprite DirectX 9.0C绘制2D动画

最近我一直在不停地问有关2D游戏制做的技术。继上一篇DirectX9中的二维图片的加载以后,我再发一篇关于通过ID3DXSprite来实现DirectX 9.0C绘制2D动画的帖子,希望对大家有所帮助。

DirectX9中的二维图片的加载
http://www.dingge.com/forum/dispbbs.asp?boardID=46&ID=5578
通过ID3DXSprite来实现DirectX 9.0C绘制2D动画
http://www.dingge.com/forum/dispbbs.asp?boardid=46&id=5581

在DirectX 8 以前,2D都是DirectDraw来完成的,是Direct中非常重要的一个部分,但是到了DirectX 8以后,DirectDraw被合并到 DirectX Graphics 当中了,所以在那以后就很少有人谈到如何用DirectX Graphics 实现2D效果。大多数需要2D的人都不辞辛苦用DirectDraw来实现了,毕竟用Direct 7的东西,后面的都是支持的。但是正如一个老外说的,喜欢用DirectDraw的人用用也无所谓,从Direct 8 以后学习的人再去学DirectDraw就不合适了,那么怎么实现自己需要的2D效果呢?我接触到了3种方法 DirectX9中的二维图片的加载就是其中之一,这里我们要讲的是第二种通过ID3DXSprite来实现DirectX 9.0C绘制2D动画

感谢Fenger提供的ID3DXSprite用法指导!!非常全面非常好!以下是引用Fenger的原话:



建立D3D和其他相关的设备应该没有问题吧.
  然后再定义一个ID3DXSprite*变量:
    ID3DXSprite* pSprite = NULL;


  然后在创建D3D设备(假如是pd3dDevice)之后, 用D3DXCreateSprite创建Sprite:
    D3DXCreateSprite( pd3dDevice, &pSprite );

  记得在设备丢失/释放时使用: SAFE_RELEASE( pSprite );

  在渲染场景的时候, 使用: 
    pSprite->Begin(x);
    ... // 具体绘制代码
    pSprite->End();

  其中的x可以是下面各值的组合, 如 D3DXSPRITE_ALPHABLEND | D3DXSPRITE_OBJECTSPACE
    D3DXSPRITE_DONOTSAVESTATE 调用Begin()或End()不保存/恢复设备状态. (如pd3dDevice->SetRenderState中设置的部分状态)
    D3DXSPRITE_DONOTMODIFY_RENDERSTATE 不是很清楚, 呵呵, 表面上看好像是不改变渲染状态...
    D3DXSPRITE_OBJECTSPACE 不改变世界矩阵(WORLD)/投影矩阵(TRANSFORM)以及视点矩阵(VIEW), 使用设置在D3DDevice上的矩阵, 如果不指定这个标志, 3个矩阵自动改变为屏幕空间座标
    D3DXSPRITE_BILLBOARD BillBoard, 很清楚吧, 所有的Sprite都全部自动旋转来对着观看着
    D3DXSPRITE_ALPHABLEND 让Sprite支持AlphaBlend, 很重要, 几乎每次调用Begin都要指定此标志, 另外, D3DRS_ALPHATESTENABLE 状态必须设置为 TRUE, D3DBLEND_SRCALPHA / D3DBLEND_INVSRCALPHA 分别为源混和状态和目标很合状态
    D3DXSPRITE_SORT_TEXTURE Sprite会按照渲染先后排序, 当渲染在同一个深度的Sprite推荐使用.
    D3DXSPRITE_SORT_DEPTH_FRONTTOBACK 按照从前到后的渲染顺序对Sprite排序, 当在不同深度渲染有透明信息的Sprite时推荐使用.
    D3DXSPRITE_SORT_DEPTH_BACKTOFRONT 按照从后到前的渲染顺序对Sprite排序, 当在不同深度渲染透明Sprite时推荐使用
  一般就是D3DXSPRITE_ALPHABLEND, 或者根据需要再加上D3DXSPRITE_OBJECTSPACE, 其他的我都不怎么用.....
  中间的绘制代码使用 pSprite->Draw, 函数原型为:
  HRESULT Draw(
    LPDIRECT3DTEXTURE9 pTexture,
    CONST RECT *pSrcRect,
    CONST D3DXVECTOR3 *pCenter,
    CONST D3DXVECTOR3 *pPosition,
    D3DCOLOR Color );
  pTexture 是需要绘制的贴图
  pSrcRect 是需要绘制的贴图上的一个矩形区域, 绘制整过贴图可以指定为NULL.
  pCenter 是绘制的中心座标(旋转时会以此点为中心), 指定NULL表示中心座标为(0,0,0)
  pPosition 是绘制的位置座标, 也可以指定NULL表示(0,0,0)
  Color 是绘制的颜色, 一般情况下指定为 0xffffffff. 最高位到底位的各8字节为Alpha, 红, 绿, 蓝, 如果指定 0x80ffffff就是半透明贴图. 如果0xffff0000就只保留贴图里的红色分量, 具体功能自己体会. 当然贴图本身可以包含Alpha信息.

  需要旋转等功能可以使用 pSprite->SetTransform(), 函数原型为:
  HRESULT SetTransform( CONST D3DXMATRIX *pTransform );
  相信这个不用解释都很清楚了吧.

  最后再提醒一点: pSprite->Begin和pSprite->End 必须成对的出现在 IDirect3DDevice9::BeginScene 和 IDirect3DDevice9::EndScene 之间.





前一种方法我们说过了,是单纯的图片加入,对于游戏而言没有太大的用处,游戏里面毕竟动态的东西比较多,怎么让他动起来呢?我们先看一下源代码。

(本帖子不分析代码,主要留作讨论。代码分析在《超级马里奥.net游戏代码完全分析》中,欢迎下载)

http://www.dingge.com/forum/dispbbs.asp?boardID=47&ID=5582&page=1

以下代码在 Microsoft DirectX 9.0 SDK Update (August 2005)环境运行通过,如果遇到编译不通过在下面留言。

把SDK中底个例子(纹理)中的banana.bmp(或者自己找一个不要太小的bmp文件)考到你的程序目录下。





//--------------------------------程序2--------------------------------------
//                             学自网络        回馈网络
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <d3dX9.h>
//-----------------------------------------------------------------------------
LPDIRECT3D9              g_pD3D        = NULL; 
LPDIRECT3DDEVICE9        g_pd3dDevice = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVB         = NULL; 
LPDIRECT3DTEXTURE9   g_pTexture   = NULL;
LPD3DXSPRITE    g_pSprite   = NULL;
struct CUSTOMVERTEX
{
     FLOAT x, y, z, rhw; 
     DWORD color;       
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)

RECT rct;

//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
SetRect( &rct, 0,200, 100, 250 );
     if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
         return E_FAIL;
     D3DPRESENT_PARAMETERS d3dpp;
     ZeroMemory( &d3dpp, sizeof(d3dpp) );
     d3dpp.Windowed = TRUE;
     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
     d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
    
     if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                       D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                       &d3dpp, &g_pd3dDevice ) ) )
     {
         return E_FAIL;
     }
     g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
     g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

D3DXCreateSprite( g_pd3dDevice, &g_pSprite );
      if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, "banana.bmp", &g_pTexture ) ) )
     {

         if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, "..\\banana.bmp", &g_pTexture ) ) )
         {
             MessageBox(NULL, "Could not find banana.bmp", "Textures.exe", MB_OK);
             return E_FAIL;
         }
     }

     g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
     return S_OK;
}

//-----------------------------------------------------------------------------
HRESULT InitVB()
{
     CUSTOMVERTEX vertices[] =
     {
         { 50.0f,   50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color
         { 250.0f, 50.0f, 0.5f, 1.0f, 0xff00ff00, },
         { 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, },
   { 250.0f, 250.0f, 0.5f,1.0f, 0xff00ffff, },
     };
     if( FAILED( g_pd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX),
                                                   0, D3DFVF_CUSTOMVERTEX,
                                                   D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
     {
         return E_FAIL;
     }
   
     VOID* pVertices;
     if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
         return E_FAIL;
     memcpy( pVertices, vertices, sizeof(vertices) );
     g_pVB->Unlock();
     return S_OK;
}
//-----------------------------------------------------------------------------
VOID Cleanup()
{
     if( g_pVB != NULL )        
         g_pVB->Release();
     if( g_pd3dDevice != NULL ) 
         g_pd3dDevice->Release();
     if( g_pD3D != NULL )       
         g_pD3D->Release();
}
VOID Render()
{
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );

     if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
     {
  
   g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
         g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
         g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

   if ( SUCCEEDED( g_pSprite->Begin(D3DXSPRITE_ALPHABLEND) ) )
   {
    rct.right +=1;
    rct.left +=1;
   
    g_pSprite->Draw(g_pTexture, &rct, NULL, NULL, 0xffffffff);
    g_pSprite->End();
   }

       
         g_pd3dDevice->EndScene();
     }
   
     g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
     switch( msg )
     {
         case WM_DESTROY:
             Cleanup();
             PostQuitMessage( 0 );
             return 0;
     }
     return DefWindowProc( hWnd, msg, wParam, lParam );
}
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
   
     WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
                       GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                       "D3D Tutorial", NULL };
     RegisterClassEx( &wc );
     HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 02: Vertices",
                               WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                               GetDesktopWindow(), NULL, wc.hInstance, NULL );

     if( SUCCEEDED( InitD3D( hWnd ) ) )
     {
        
         if( SUCCEEDED( InitVB() ) )
         {
       
             ShowWindow( hWnd, SW_SHOWDEFAULT );
             UpdateWindow( hWnd );
        
             MSG msg;
             ZeroMemory( &msg, sizeof(msg) );
             while( msg.message!=WM_QUIT )
             {
                 if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                 {
                     TranslateMessage( &msg );
                     DispatchMessage( &msg );
                 }
                 else
                     Render();
             }
         }
     }
     UnregisterClass( "D3D Tutorial", wc.hInstance );
     return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值