您的位置:首页 > 其它

一篇文章搞定DX9.0c 环境里的3DXSpriet !!

2010-06-23 15:56 316 查看
四年前写过一篇《一篇文章搞定3DXSpriet !! 》得到了很多的反馈,现在那篇文章中的好多代码已经不可以再用了,所以对其中的一些代码做了改动,为了方便初学者掌握3DXSpriet,再写一篇关于dx9.0c 环境下的3DXSpriet文章,时间比较仓促,估计里面有一些Dx9b的没有修改过来,错误之处敬请谅解,在这里权作抛砖引玉,希望大家参与讨论!

A. 什么是ID 3DXSpriet

我们有了创建win窗口的基础下来我们谈谈2D游戏中最关键的函数 3DSprite,通过对函数的运用,你会马上发现这是一个多么简单易用的2D绘图函数。还是老办法,在你的Microsoft DirectX 9.0_c SDK 环境里运行以下下列代码(以下代码来自通过ID3DXSprite来实现DirectX 9.0C绘制2D动画)。

找一张图片(或者自己找一个不要小于200*200像素的图片文件)考到你的程序目录下作为纹理的加载。
//-----------------------------------------------------------------------------
// File: Vertices.cpp
//
// Desc: In this tutorial, we are rendering some vertices. This introduces the
// concept of the vertex buffer, a Direct3D object used to store
// vertices. Vertices can be defined any way we want by defining a
// custom structure and a custom FVF (flexible vertex format). In this
// tutorial, we are using vertices that are transformed (meaning they
// are already in 2D window coordinates) and lit (meaning we are not
// using Direct3D lighting, but are supplying our own colors).
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include
#pragma warning( disable : 4996 ) // disable deprecated warning
#include
#pragma warning( default : 4996 )

//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device
LPDIRECT3DTEXTURE9 g_pTexture = NULL;
LPD3DXSPRITE g_pSprite = NULL;

//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
// Create the D3D object.
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;

// Set up the structure used to create the D3DDevice
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

// Create the D3DDevice
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
{
return E_FAIL;
}

D3DXCreateSprite( g_pd3dDevice, &g_pSprite );

if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, "lid9P0ADGHTJA.jpg", &g_pTexture ) ) )

{

if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, "..//lid9P0ADGHTJA.jpg", &g_pTexture ) ) )

{

MessageBox(NULL, "Could not find pic", "Textures.exe", MB_OK);

return E_FAIL;

}

}

// Device state would normally be set here

return S_OK;
}

//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
VOID Cleanup()
{
if( g_pd3dDevice != NULL )
g_pd3dDevice->Release();

if( g_pD3D != NULL )
g_pD3D->Release();
}

//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
VOID Render()
{
// Clear the backbuffer to a blue color
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );

RECT rct = {0,0,512,512};
// Begin the scene
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{

if ( SUCCEEDED( g_pSprite->Begin(D3DXSPRITE_ALPHABLEND) ) )
{
g_pSprite->Draw(g_pTexture, &rct, NULL, NULL, 0xffffffff);
g_pSprite->End();
}
// End the scene
g_pd3dDevice->EndScene();
}

// Present the backbuffer contents to the display
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
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 );
}

//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
// Register the window class
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"D3D Tutorial", NULL };
RegisterClassEx( &wc );

// Create the application's window
HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 02: Vertices",
WS_OVERLAPPEDWINDOW, 100, 100, 800, 600,
NULL, NULL, wc.hInstance, NULL );

// Initialize Direct3D
if( SUCCEEDED( InitD3D( hWnd ) ) )
{
// Show the window
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );

// Enter the message loop
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;
}


B. 怎么运用3DXSpriet 绘制图像

开始3DSprite 的语法学习,本小节本手册的重点内内容,但并非难点,希望认真学习。

从函数的名字可以看出,这是一个D3D的函数,有很多人很迷惑,我们用D3D的方法来实现2D效果,不是大材小用,浪费资源吗?所以有很多人重操旧业,用DirectX 7.0 里面的DirectDraw来实现2D效果,认为这样绘制出来的2D效果速度快资源占用率低。在这里我也只想说3DSprite在资源上的确浪费了,当然理论上速度也要比DirectDraw慢。但是它支持硬件加速,所以在实际上它比DirectDraw快了而不是慢了。如果你有兴趣或者有自己的看法,可以到 D3D實現2D游戲在效率上會不會比用DirectDraw差? 里来讨论。

本函数在用的时候要注意,它的格式:

pSprite->Begin();
g_pSprite->Draw();... // 具体绘制代码
pSprite->End();

要把图像绘制到屏幕上,我们就必须用到一个函数g_pSprite->Draw(),g_pSprite->Draw()就是我们用来绘制图像的函数,我们所有的图像,都要依靠它才能显示在我们的窗口中。g_pSprite->Draw()函数必须存在于pSprite->Begin()和pSprite->End();之间,而且后面这两个函数必须成对出现 IDirect3DDevice9::BeginScene 和 IDirect3DDevice9::EndScene之间。

3DSprite要绘制图像,那么就必须加载图片,我们用莱加载的图片的方法是利用D3D中加在纹理的方法,因此,我们的还必须学习一些D3D的一些知识,如果你看过DirectX 9 进阶手册----SDK例题分析的话,那就没有多大问题了。如果没有,希望你还是看看相关书籍。那么跟着我来看看《快乐西游》中的一些代码(上一节那个完整程序中也可以查看相关内容)。

//--------------------------------程序《快乐西游》显示部分代码--------------------------------------
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++Display.cpp 游戏加载D3D图像部分++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
//////本部分完全是为了用于显示最终的图形//////////
//////至于由什么来要求显示图像,本部分并不关心////
///////////////////////////////////////////////////////////////////////
#include <d3dX9.h>
//-----------------------------------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL; //设备对象
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; //设备指针
LPDIRECT3DTEXTURE9 g_pTexture = NULL; //纹理指针
LPD3DXSPRITE g_pSprite = NULL; //SPRITE对象


运行2D代码,加载一个头文件d3dX9.h就可以了,对于初学者而言,为了让自己的代码

能够编译成功,总是加载很多的头文件,这是一个很不好的习惯。

前三个变量声明是为了建立D3D设备加载图片纹理的,在我们使用g_pSprite->Draw()之前,我们必须定义一个ID3DXSprite*变量

LPD3DXSPRITE g_pSprite = NULL; //SPRITE对象

接下来我们要在创建D3D设备(假如是g_pd3dDevice)之后, 用D3DXCreateSprite创建Sprite:

 D3DXCreateSprite( g_pd3dDevice, & g_pSprite);

释放资源的时候我们用到的是

 g_pSprite->Release ();

然后我们在正常的D3D程序Render中按照上面的要求放置好g_pSprite->Draw()的位置就可以了。

C. 详解Spriet->draw( )函数

不用说,这是我们的核心内容了。Draw()函数在DirectX 9.0c以前是有7个参数的,到了DirectX 9.0c的时候变成了5个参数,同时对pSprite->Begin(x)中的x也有了很多的设置,这个有兴趣的朋友可以参考DirectX9_b技术文档了解相关内容,在这里就不多阐述。因为我们用的是DirectX9c SDK;而且据我所知,微软新版DirectX 11 将是全新的DirectX版本,而且不对以前DirectX 兼容(不敢相信这是真的)。也就是说,以后要学习的DirectX 完全是一个全新的内容,那么说来生存在这个夹缝中的DirectX10 真是一个高不成低不就的鸡肋了。

D3DXCreateTextureFromFile( g_pd3dDevice, "bg.png", &g_pTexture );

这个函数加载的图片bg.png,你也可以根据自己的喜好加载别的格式的图片,比如bmp文件。我个人比较喜欢.png格式的图片,它是简单的支持背景透明的图片格式,简单好用。

我们现在来看DirectX9_b环境里的Draw()函数。

g_pSprite-> Draw(g_pTexture, &rct, NULL, NULL,NULL,NULL,0xffffffff) ;

g_pSprite-> Draw(g_pTexture //纹理图片

&rct //纹理图片中的矩形区域

NULL //绘制图片的伸缩矩阵

NULL //绘制图片的旋转矩阵中心坐标

NULL //绘制图片的旋转角度

NULL //绘制图片的平移矩阵

0xffffffff); //绘制图片时的颜色

v 参数 &rct
函数&rct指的是加载图片中的矩形区域

RECT rct_man;

SetRect( &rct_man,0,930,60,1024);

此主题相关图片如下:



SetRect( &rct_man,x1,y1,x2,y2);
v 参数 伸缩矩阵

这个参数没有值的话就可以写NULL,如果准备付值,就可以通过&D3DXVECTOR2(x,y)来付值,在这个函数中,x,y分别表示在x轴和y轴上的放大倍数,放大中心点如图所示:



此主题相关图片如下:


我们游戏当中有很多的伸缩变换,实际都是从下往上方法缩小的,也就是说一般最下面的边是不变的,而放大中心并不是左下角心,这样的话可能会给我们实际制作游戏当中带来很多不便。这就要求我们在游戏设计当中合理的利用其余的参数设置来做到这一点。

v 参数 旋转矩阵坐标

旋转中心坐标如果付空值NULL的话,默认的坐标同样在图片的左做上角。同样可以通过&D3DXVECTOR2(x,y)来付值改变它的坐标位置。

此主题相关图片如下:



在游戏当中一般我们采用的是中心旋转。

v 参数 旋转角度

这个参数的参数类型有别于其他几个,它采用的是Float浮点型,它标示的是上面围绕旋转中心的旋转的角度。

v 参数 平移矩阵

平移矩阵是我们接触使用最多的一个矩阵,它就是表示把源图片中所选择的&rct矩阵内的图像,绘制到窗口的什么地方,付空值NULL的话,默认的坐标在窗口的左做上角(0,0)点。

如果准备付值,就依然是通过&D3DXVECTOR2(x,y)来付值,这里的x,y就是相对于窗口内部的(0,0)点的坐标,我们通过这个坐标的变化,在同一窗口绘制不同位置的元素,实现例如人物的移动等。

此主题相关图片如下:




v 参数 绘制背景颜色

这个非常简单,就是绘制图片的时候背景与图片的混合色,如果是白色的话,就是绘制图片原有的色彩;但是如果有特殊需求,可以采用色彩混合的方式实现不同的显示效果比如灯光色彩的变化等。通常才用0xffffffff。其中0xff的这两个ff表示透明度ff表示不透明,00表示全透明,也就是画了一块玻璃上去。

以上讲的是在sdk 9.0_b以前版本的,要是sdk 9.0_b以后的版本会是什么样子呢?看懂了上面的例子,看下面就简单了:

HRESULT Draw(
LPDIRECT3DTEXTURE9 pTexture, //纹理图片
CONST RECT * pSrcRect, //纹理图片中的矩形区域(就是你想画的部分)
CONST D3DXVECTOR3 * pCenter, //旋转中心
CONST D3DXVECTOR3 * pPosition,//平移矩阵
D3DCOLOR Color //渲染颜色,白色表示正常显示原图
);

sdk 9.0_c 参数大同小异,不同的是后面旋转和缩放不再Draw函数中设置了,而是通过矩阵来设置的:

1) 利用D3DXMatrixTranslation移动精灵,D3DXMatrixTranslation函数原型为:
D3DXMATRIX * D3DXMatrixTranslation(
D3DXMATRIX * pOut, // 平移矩阵
FLOAT x, // 目的位置x坐标
FLOAT y, // 目的位置y坐标
FLOAT z // 目的位置z坐标
);
pOut参数用于指向一个矩阵,该矩阵用于将精灵移动到x、y、z所指定的位置处。
x参数用于指定精灵移动位置的x坐标。
y参数用于指定精灵移动位置的y坐标。
z参数用于指定精灵移动位置的z坐标,在2D游戏设计中此值为0。
如果需要将精灵移动到(10,8)位置处,实现代码如下:
D3DXMATRIX matWorld; // 定义矩阵

D3DXMatrixTranslation(&matWorld, 10, 8, 0); // 设置平移位置
m_pSprite->SetTransform(&matWorld); // 移动精灵
2) 利用D3DXMatrixRotationZ旋转精灵。D3DXMatrixRotationZ函数原型为:
D3DXMATRIX * D3DXMatrixRotationZ(
D3DXMATRIX *pOut, // 旋转矩阵
FLOAT Angle // 旋转角度
);
pOut参数用于指向一个矩阵,该矩阵用于将精灵旋转Angle角度。
Angle参数用于指定旋转精灵弧度。
如果需要将精灵旋转90°,实现代码如下:
D3DXMATRIX matRotationZ;

FLOAT m_Angle = D3DX_PI/2;

D3DXMatrixRotationZ(&matRotationZ, m_Angle);

m_pSprite->SetTransform(&matRotationZ);
D3DXMatrixRotationZ函数m_Angle参数表示旋转的弧度,所以需要将角度转换成弧度。D3DX_PI在Direct3D中用来表示180°的弧度值。

矩阵是可以传递

// 将旋转矩阵和平移矩阵合并为一个变换矩阵
D3DXMatrixMultiply(&matWorld, &matRotationZ, &matWorld);

// 设置变换
m_pSprite->SetTransform(&matWorld);

到此为止,ID3DSprite就讲完了 这些内容都来自<快乐西游>模仿秀 如果你想了解更多内容的话,请在下面留言。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: