四年前写过一篇《一篇文章搞定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就讲完了 这些内容都来自<快乐西游>模仿秀 如果你想了解更多内容的话,请在下面留言。

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

  1. 超硬核!!!一篇文章搞定TCP、UDP、Socket、HTTP(详细网络编程内容+现实解释三次握手四次挥手+代码示例)【网络编程 1】

    TCP.UDP.Socket 一天面试的经验: 什么是网络编程 网络编程中两个主要的问题 网络协议是什么 为什么要对网络协议分层 计算机网络体系结构 1 TCP / UDP 1.1 什么是TCP/IP ...

  2. Android NDK开发之旅(2):一篇文章搞定Android Studio中使用CMake进行NDK/JNI开发

    Android NDK开发之旅(2):一篇文章搞定android Studio中使用CMake进行NDK/JNI开发 (码字不易,转载请声明出处:http://blog.csdn.NET/andrex ...

  3. 一篇文章搞定GVIM(根据工作经验持续更新)

    文章目录 0.引言 1.在Linux下面安装VIM 2.基本操作 2.1三种模式 2.1 保存退出:wq没反应?! 2.2 解决鼠标不能用的问题 2.3 VIM上下左右移动hjkl 2.4 跳转到第n ...

  4. 一篇文章搞定百度OCR图片文字识别API

    一篇文章搞定百度OCR图片文字识别API https://www.jianshu.com/p/7905d3b12104 转载于:https://www.cnblogs.com/chongdongxia ...

  5. python基础知识-一篇文章搞定Python全部基础知识

    原标题:一篇文章搞定Python全部基础知识 前言: 1.Python软件安装 第一章.字符串及数字变量 1.变量 要点提炼:Python变量为强类型动态类型.换言之,变量很任性,你给他int,他就是 ...

  6. 一篇文章搞定《RecyclerView缓存复用机制》

    一篇文章搞定<RecyclerView缓存复用机制> 前言 零.为什么要缓存 一.RecyclerView如何构建我们的列表视图 二.缓存过程 三.缓存结构 1.mChangedScrap ...

  7. 一篇文章搞定java中的垃圾回收机制面试题

    一篇文章搞定java中的垃圾回收机制面试题 任何语言在运行过程中都会创建对象,也就意味着需要在内存中为这些对象在内存中分配空间,在这些对象失去使用的意义的时候,需要释放掉这些内容,保证内存能够提供给新 ...

  8. 一篇文章搞定《Android布局优化》

    ------<一篇文章搞定Android布局优化> 前言 为什么要进行布局优化? Android绘制原理 双缓冲机制 布局加载原理 布局加载优化的一些方法介绍 AsyncLayoutInf ...

  9. 一篇文章搞定交换机的三种端口类型

      啥?交换机的三种端口类型是哪三种?他们有哪些特点?数据处理过程是怎样?你可千万别再一问三不知了,一篇文章帮你搞定. 一.交换机三种端口类型特点: 二.交换机接口出入数据处理过程: 理解这三个名词解 ...

最新文章

  1. 对Document library中修改文档的Author之实现修改在list(三)
  2. LeveyPopListView
  3. 15分钟了解Apache Phoenix(HBase的开源SQL引擎)
  4. STL-容器库101--array【C11】
  5. 黑科技抢先尝(续2) - Windows terminal中Powershell Tab的美化全攻略
  6. TCP如何利用不可靠的IP协议实现可靠传输
  7. html读取媒体长度,用媒体查询media根据屏幕分辨率大小确定网页宽度
  8. FastReport.Net使用:[1]屏蔽打印对话框
  9. github每次push时自动输入用户名密码
  10. usb转rs485 linux驱动下载,USB转485万能驱动下载
  11. TFN FAT130 便携式手持频谱分析仪 9KHZ到6GHZ范围高端频谱测试仪
  12. v6使用手册 天正电气t20_T20电气软件官方版下载-TElecT20V6 附安装教程 - 河东下载站...
  13. Greedy Method
  14. hdu 3853 LOOPS
  15. python爬虫入门之————————————————案例演练
  16. 判断二极管导通例题_几种二极管的检测方法(普通,稳压,双向触发)
  17. 不改一行代码!快速迁移 Express 应用上云
  18. 985毕业,沪漂10年,月薪4w,我却活得一地鸡毛
  19. uniapp小程序开发自定义相机、拍照、上传
  20. 马云唱京剧《空城计》,柳传志说相声:“商界春晚”大佬们真会玩(附视频)...

热门文章

  1. STM32笔记 (十三)定时器输入捕获(利用定时器捕获高电平时间)
  2. 利用JavaScript生成动态添加歌单
  3. 技嘉显卡测试用什么软件,独家揭秘评测微星和技嘉显卡区别是?哪个好?口碑反馈揭秘...
  4. greasemonkey_询问操作方法:Chrome中的Greasemonkey,为Media Center布线和自定义Windows 7跳转列表...
  5. Unity3D GPU Instancing测试
  6. Win32:INI文件读写结构体/Int/String/遍历
  7. 2021-2027全球与中国牛肉罐头市场现状及未来发展趋势
  8. python访问陌生人qq空间_Python爬虫获取QQ空间信息(上)
  9. 网站带不带www真的不一样,很多新手不知道区别会被坑死的
  10. mpls接收udp并处理