DirectDraw基本图形概念
DirectDraw基本图形概念
返回上级
在上一章里,我们尝试了一个非常简单的DirectDraw应用程序,可以看到,DirectDraw编程对一个C或C++程序员来说并不是陌生和难以接近的。在这一章里,我们将介绍Directdraw编程中所经常用到的图形方面的知识,在深入进行DirectDraw编程之前,领悟这些最基本的图形概念是非常必要的。
1、像素和分辨率 2、RGB色彩 3、设备无关位图(DIB) 4、位深度(Bit depth) 5、抖动处理(Dithering) 6、调色板(Palette) 7、GDI与DirectDraw | 8、位块传送(Blit) 9、翻页(Page flipping) 10、矩形(Rectangle) 11、精灵动画(Sprite animation) 12、关键色(Color Key) 13、补丁(Patching) 14、范围检查与碰撞检测 |
1、像素(Pixel)和分辨率(Resolution)
返回目录
首先,让我们从电脑显示器屏幕上的基本单位棗像素说起。对用户来说,像素指的是显示器在某种分辨率状态下所能表达图象的最小单位。你可以把它简单的理解为一种类似于马赛克的东西。像素的大小与你当前的显示分辨率有关,现在所有的SVGA显示器都支持多种分辨率,比如通常所说的640x480、800x600等。许多人错误的将像素的大小与显示器的点间距(Dot Pinch)混淆了,其实它们指的不是同一个东西。当你用放大镜观察显示器屏幕时,你会发现图象实际是由许许多多红,绿,蓝整齐排列的小点组成,你可能会认为这就是像素,那么你就错了。这实际上是显示器光栅的一个扫描点,它是荧光屏后部的三束电子枪发射电子透过一层致密的网打到荧屏反面而发出的荧光,人们常说的0.28的彩显意即:屏幕上相临两个扫描点的平均间距为0.28毫米。一个像素是由若干个这样的扫描点组成的。专业的说,在某种分辨率状态下,显示器的水平(垂直)像素的个数,实际上等于一次水平(垂直)扫描期间,电子束的通短强弱状态能够发生变化的次数。一台彩显所能达到的最大分辨率受到这台彩显的尺寸和点距的限制。
显然,显示器型号越大,点间距越小,则它所能达到的分辨率就越高,那么,它所显示的图象就越清晰,表现得越细腻。
2、RGB色彩
返回目录
现实生活中,我们所能分辨的所有颜色都能用三原色:红、绿、蓝合成出来,称为RGB色彩模式。用RGB方式合成颜色主要用于发光设备,如计算机显示器。通过分别调节红,绿,蓝三束电子枪的强度,就可产生一个广泛的色彩范围。由于色彩的产生来源于RGB三种色彩光强度的叠加,所以,这种方法被称为彩色叠加。
值得一提但与我们的DirectDraw编程基本上没有什么关系的另一种色彩表示模式是CMYK色彩模式,代表青,粉,黄三种可减基色,加上黑色作对比,常用于打印,感光材料,胶片等。每种基本色从照射到打印页的白光中吸取某些色彩,由于CMYK方式通过从白光中吸取特定的色彩,所以被称为彩色削减。此外,还有HSI(也称HSL)色彩模式,它代表Hue , Saturation 和 Intensity 。Hue 是我们所认为的色调,如红橙黄绿青蓝紫等,Saturation描述该色调颜色的饱和度,Intensity 描述亮度。
RGB 颜色方式对于显示器来说是唯一适用的彩色混合方法,而CMYK则是适用于打印和印刷的彩色混合方法,HSI 则是一个很直观的定义彩色的方法。现在的许多图形软件中都同时具有这三种定义颜色方法的应用。但是,不论用那种方法给颜色取值,最终都必须转化为RGB方式才能为显示器所认识接收并显示出来。
在几乎所有的编程中,当然也包括DirectDraw,都是采用标准的24位RGB模式定义一个颜色,用三个从0到255的数值来分别代表R、G、B三个分量,每个分量都有256种亮度级别。当三种元素全被置为0,像素显示黑,通常表示为RGB(0,0,0);当全部置为255,像素显示为白,表示为RGB(255,255,255)。
3、设备无关位图(DIB)
返回目录
位图图象(也称点阵图象)准确的说是什么呢?它们是数据元素的集合,这些数据元素决定在了在图片的某个具体位置是什么颜色。这就好比我们用许许多多的马赛克来拼图案一样,每个马赛克虽然只有一种颜色,但你看到的只是整个美丽的图案,而不是某一个马赛克。当图象显示在显示器屏幕上时,正如前面提到的那样,这一个个的马赛克就是像素。
Windows中,当然还包括DirectX,都使用设备无关位图DIB(Device-Independent Bitmap)作为其最基本的图象文件格式。
- 之所以称之为设备无关位图(DIB),其实是为了与设备相关位图(DDB:Device dependent bitmap)相区别。由于只有Windows 3.0以前的版本才广泛使用设备相关位图DDB,Windows 95和Windows NT及以后的版本使用的都是设备无关位图DIB,所以,“设备无关位图”这个名称在当前已没有其现实的含义。在大多数情况下,我们将其简称为位图(Bitmap)。
从本质上说,DIB是一个包含了图象的各种信息的文件,包括图象的尺寸,使用的颜色个数及其颜色值,还有每个像素的颜色数据等。此外,一个DIB中还包含了一些极少使用的参数,象文件压缩类型、重要颜色,还有图象的物理维数等。DIB文件通常具有“.bmp”扩展名,偶尔也会将“.dib”作为其扩展名。
Windows对DIB位图有规定的格式,在我们学习了位深度和调色板的概念之后,对DIB格式再做详细的解释。
- 与位图格式相对的是矢量格式,由于它是用形状和相互关系来描述图象,WMF文件就是一种典型的矢量图,它的特点是具有极大的灵活性,可以任意缩放不失真,且存储空间相对较小,但矢量图由于其描述图象的方式与位图完全不同,不适用于图象处理的领域。在以后的DirectDraw编程中,我们所指的图象特指位图图象。
4、位深度(Bit depth)
返回目录
计算机中,一个字节(Byte)是由8个位(Bit)组成的。位深度指的是用来描述某状态值所使用的计算机位的个数。在DirectDraw中,通常用位深度来代表位图中的颜色值所使用的位个数,从另一个意义上讲,位深度表示了位图中颜色的丰富程度。
1字节等于8位二进制数,所以一字节所能表达的十进制整数的范围是从0到255,即一字节能且最多只能反映出256(2的8次方)种不同的状态。在位图中,如果用其中每一种状态代表图象中某一个点的颜色,那么最多可以得到256种不同的颜色,这就是我们常见的8位(256色)的位图。同理,如果用1位二进制数来表示某一点的颜色,那么只能得两种(2的1次方)颜色,这就是一幅两位的黑白位图;如果用四位二进制数则产生16种颜色(2的4次方),这是一幅4位(16色)的位图,用24位产生16M种颜色(2的24次方)等,这就是一幅24位真彩位图。由于每幅图形文件都用确定的位数来代表颜色(1、2、4、8、16、24或32位),所以我们所见的图片颜色数都为2的n次方(n=位深度)。
显然,一幅图象的位深度越高,那么它所能表现的颜色也越多,色彩也就越丰富。通常,在一般情况下,8位(256色)的图片已可满足需要,但在一些要求高质量图象的场合,16或24位的图象是必须的。当然,颜色位深度的增加,也势必带来所需存储空间的膨胀,没有经过压缩的相同大小的24位图象所需的存储空间是8位图象的3倍,这也会带来文件读取和操作速度的降低,所以在需要高速度显示图象的场合,使用低位深度的图象是必要的。
5、抖动处理(Dithering)
返回目录
在低位深度的图象中,由于颜色总数的限制,有些颜色无法显示出来,为了模拟出那些颜色以提高显示效果,广泛采用了一种称作抖动处理(dithering)的方法,也称半色调处理(Halftoning)。它是指用交替的点图案去模拟在图象中不能使用的颜色的过程。单色图象是最简单的格式,一般由黑色和白色组成,在一些单色图象如黑白照片和有深浅的图案中,会使用各种灰度,这种图象常被称为灰度图象(Grayscale Image)。由于人眼会把一个很细致的黑白相间的图案解释成灰色,所以灰度图象也可使用单色文件格式,数据仍然可以是黑和白。使用黑色或某一种单色的点获得连续的该色灰度的过程就是抖动处理。抖动处理被更多的用在那些低位数彩色图象文件中,与不采用这种处理相比,它具有更好的显示效果。
6、调色板(Palette)
返回目录
显示器及显示卡与显示器的接口都采用模拟方式来处理色彩,因此,它们都具有几乎无限的色彩显示和传输能力,但主机和显示卡只能用数字方式来表示和处理色彩,在用数字方式表示色彩时,如果要获得更丰富,更细腻的色彩就需要增加色彩的位深度,这就需要更大容量的显示存储器,相应的也就需要更高的处理速度,同时分辨率的提高也对显示存储器的容量提出了很高的要求。
为了尽量降低对显存的需求,在Windows中可以使用一种间接的色彩表示方法,这就是调色板(Palette)表示法。它的含义是:用一个颜色索引(Color Index)来代表各个像素点的颜色,而不是直接用红,绿,蓝三基色的亮度值来确定每个像素点的颜色。色彩表(Color table)是一个包含了若干颜色索引和该索引所对应的真实颜色值的表,这个色彩表就是调色板。
这种方法就好比给学校里的每一个学生规定一个专用的学号,在很多场合,并不需要知道某个同学的实际姓名,只要知道他的学号即可,显而易见,使用学号无疑会给学校的学员管理工作带来了极大的便利。调色板就好比一张记载了学生学号及其姓名的名册,颜色索引值就是学生的学号,RGB颜色值就是学生的姓名。
使用调色板的好处就在于:索引值占用较少的数据位(1、2、4或8位),而真实颜色值占用较长的数据位(24位,即3字节,分别代表红,绿,蓝三基色的颜色亮度值,从0到255)。由于使用了调色板,既提高了图象显示效率,又减少了对显存的需求。
调色板的颜色索引主要采用4或8两种位深度:4位位深度可有16种不同取值,对应于显示器的16色显示模式,这时一屏最多只能显示16种不同的颜色;8位位深度可有256种不同的取值,对应于显示器的256色显示模式,一屏最多只能显示256种颜色。于是,问题就开始出现了,当你在16色模式下显示一幅256色或更高位深度的的图象时,你将会看到本应色彩鲜艳的图片变得面目全飞,罪魁祸首就是调色板,由于它使得同时显示在屏幕上的不同颜色最多只能有16种(对应于16色模式下),于是Windows首先从图象中挑选了16种使用频率最高的颜色指定给调色板,对于所有其它的颜色,从调色板中挑选一个最接近的颜色显示出来。在256色模式下,要同时显示两幅不同调色板的256色位图时,也会发生这种图象失真的情况。
7、GDI与DirectDraw
返回目录
在大多数的Windows编程中,开发者们使用的是Win32的函数以获得访问绘图页面的能力,例如,使用GetDC函数,可以获得设备环境(DC?/FONT>Device context)。在获得设备环境之后,你就可以开始进行对屏幕的绘图了。Win32的所有图形函数都是由Windows系统的一个独立完整的模块所提供,这就是图形设备接口(GDI?/FONT>Graphics device interface)。GDI为计算机用户和计算机硬件之间提供了一个抽象层,在此层的基础上,用户可以通过简单的调用Win32的图形函数进行图形显示。
GDI的一大缺憾就是,它不是为具有高表现力的多媒体软件和游戏而设计的,设计者们开发它的主要用途是运行商业应用软件诸如:Word字处理软件、Excel电子表格、Explorer浏览器等。GDI只提供了访问系统主存的能力,而不提供直接访问显存的能力,并不能从具有某些加速特性的显卡中获得其优良特性。简而言之,GDI对绝大多数的商业软件来说是相当完美的,但对于多媒体软件和游戏来说,它却是低速和低效的。
另一方面,DirectDraw可以提供给开发者代表了真实显示内存的绘图页面。这意味着,只要你使用了DirectDraw,你就可以直接操纵显卡上的内存,图形显示变得出奇的快速。而且这些页面代表了显存中连续的内存块,使得在页面中寻址和读写变得非常方便。
8、位块传送(Blit)
返回目录
“Blit”是“Bit block transfer”的缩写,意为“位块传送”。顾名思义,Blit的作用是:将某一内存块的数据传送到另一内存块,前一内存块被称为“源”,后一内存块被称为“目标”。这里用的是“传送”一词,而不是“复制”,因为在Blit过程中,数据并不是被原封不动的转移,而是经过了一定的转换。
- 在许多书籍中或程序中经常可以见到的“Bitblt”、“Blt"或“Bltting”,其实也是同一个意思,前者读作['bitb'lit];后者读作[b'lit]。
在绝大多数情况下,Blit操作是针对位图图象的,因此,源数据代表的是“源位图”,目标数据代表的就是“目标位图”。图象程序开发者使用Blit的函数在内存中将某页面上的一幅位图经过一定的变换转移到另一个页面上。这种变换有很多种,每一种都有一个代码与之对应,我们称该代码为光栅操作代码(ROP?/FONT>Raster operation code)。
Blit操作被广泛的用于图形程序中,如在显示位图、移动、复制位图、位图合成、位图特效以及精灵的实现中都有blit的身影。GDI和DirectDraw中,都提供了blit的函数,如GDI中的BitBlt、StretchBlt、PatBlt等,DirectDraw中的IDirectDrawSurface3::Blt和IDirectDrawSurface3::BltFast等。
下面我们来分析一个典型的Blit的函数,GDI的BitBlt是Win32 API中一个重要的函数,关于它的详细资料可以参阅VC中的帮助,位于:Platform,SDK,and DDK Document\Platform SDK\Reference\Functions\Win32 Functions,它的原型如下:
BOOL BitBlt(
HDC hdcDest, //目标设备环境的句柄
int nXDest, //目标设备环境的矩形区域的左上角的x坐标
int nYDest, //目标设备环境的矩形区域的左上角的y坐标
int nWidth, //目标设备环境的矩形区域的宽度值
int nHeight, //目标设备环境的矩形区域的高度值
HDC hdcSrc, //源设备环境的句柄
int nXSrc, //源设备环境的矩形区域的左上角的x坐标
int nYSrc, //源设备环境的矩形区域的左上角的y坐标
DWORD dwRop //光栅操作符
);
dwRop参数是光栅操作代码(Rop),它是指源位图与目标位图以及图案刷的颜色值进行布尔运算的方式,以下列出了常用的光栅操作符。
光栅操作代码 | 含义 |
BLACKNESS | 用黑色填充目标矩形区域。 |
DSTINVERT | 将目标矩形图象进行反相。 |
MERGECOPY | 将源矩形图象与指定的图案刷(Pattern)进行布尔“与”运算。 |
MERGEPAINT | 将源矩形图形经过反相后,与目标矩形图象进行布尔“或”运算。 |
NOTSRCCOPY | 将源矩形图象经过反相后,复制到目标矩形上。 |
NOTSRCERASE | 先将源矩形图象与目标矩形图象进行布尔“或”运算,然后再将所得图象进行反相。 |
PATCOPY | 将指定的图案刷复制到目标矩形上。 |
PATINVERT | 将指定的图案刷与目标矩形图象进行布尔“异或”运算。 |
PATPAINT | 先将源矩形图象进行反相,与指定的图案刷进行布尔“或”运算,再与目标矩形图象进行布尔“或”运算。 |
SRCAND | 将源矩形图象与目标矩形图象进行布尔“与”运算。 |
SRCCOPY | 将源矩形图象直接复制到目标矩形上。 |
SRCERASE | 将目标矩形图象进行反相,再与源矩形图象进行布尔“与”运算。 |
SRCINVERT | 将源矩形图象与目标矩形图象进行布尔“异或”运算。 |
SRCPAINT | 将源矩形图象与目标矩形图象进行布尔“或”运算。 |
WHITENESS | 用白色填充目标矩形区域。 |
表中,提到了三种的基本布尔运算,分别是:反相(NOT)、与(AND)、或(OR)。还提到了异或(XOR),学过数理逻辑的人都知道,异或运算其实也是可以由前三种组合出来的。可以看出,所有的光栅操作代码都是由三种基本布尔运算组合而成。实际上,一共有256种光栅操作代码,但最常用的就是以上这15种。若想使用这15种以外的任何一种时,可以查阅VC的帮助,但在实际中,它们是极少被用到的。
图案刷(英文是Pattern, 也可翻译成模式刷,直接的意思是布料上图案的花样)是Windows资源的一种,属于Brush,它其实是一个固定大小的位图(通常为8x8像素),用来平铺填充设备环境(DC)的某一区域。它的用法与普通的刷子是没有区别的,当把一个图案刷用SelectObject函数选定给某设备环境,再在该设备环境中进行填充操作,那么所填充的不是一个单纯的颜色(选用普通的刷子时的情况),而是连续平铺的图案。
GDI的blit函数还有PatBlt和StretchBlt。它们与BitBlt大同小异,BitBlt具有Patblt的所有功能,StretchBlt除了具有BitBlt的一切功能外,它还可以将位图放大或缩小,实现缩放功能。
DirectDraw最常用的blit函数是IDirectDrawSurface3::Blt,它的原型如下:
HRESULT IDirectDrawSurface3::Blt(
LPRECT lpDestRect, //目标矩形区
LPDIRECTDRAWSURFACE3 lpDDSrcSurface, //源页面
LPRECT lpSrcRect, //源矩形区
DWORD dwFlags, //标志符
LPDDBLTFX lpDDBltFx //光栅操作代码及特效
);
DirectDraw中的Blt函数比GDI中的BitBlt函数虽然在形式上极为相似,但在内容上却有了质的飞跃。首先,从运行速度上来比较,IDirectDrawSurface3::Blt可以利用到一切可以利用的硬件加速特性,而且该操作在缺省情况下是异步执行的,这意味着程序不需要等待blit结束才返回,而是在给系统发出了blit的指令后,立即返回,然后系统在后台进行blit操作,这使程序的运行变得极为高效、快速;其次,它还支持带源和目标关键色以及z缓存和alpha 通道的blit操作,这使得用该blit函数来完成各种效果变得极更为容易。
该函数的目标页面就是调用者本身,而且矩形区域用RECT结构表示。第四个参数dwFlays表示该blit操作的类型,最后一个参数lpDDBltFx是一个包含了光栅操作代码和其它特效的结构,其中的光栅操作代码成员与Win32的是兼容的。
DirectDraw中的blit函数还有IDirectDrawSurface3::BltFast和IDirectDrawSurface3:: BltBatch。前者完成一次显存中的blit操作,在没有硬件加速的情况下,其速度可以较Blt快一些,后者完成一组blit操作。
要得到更多的关于DirectDraw中的blit函数的资料,请参阅本教程的DirectDraw参考手册。
9、翻页(Page flipping)
返回目录
在多媒体动画、动感游戏等软件中,翻页是一个相当关键的概念。与绘画师绘制动画片相比,计算机中的翻页技术与其具有相似之处。例如:绘画师在一叠相同的纸上绘画,画完一张再画下一张,在每一张上,绘画师使画面有略微的改动,于是,当你在这一叠纸上快速的翻页时,静止的图象便开始运动起来。
DirectDraw中的翻页与上面这个过程极为相似。首先,你得设置好一个翻页链结构,它由一组DirectDraw页面组成,每一个页面都可以被轮流翻页至显示屏幕。当前正好位于显示屏幕的页面,我们称之为主页面(primary surface),其后等待翻页至屏幕的页面,我们称之为后台缓存(Back buffers)。应用程序在后台缓存上进行绘图操作,然后“翻一页”,将此页面翻页成为主页面,原来的主页面成为后台缓存,翻页后,你所进行的修改可以立即显示在屏幕上。与此同时,你可以在下一个即将翻页成为主页面的后台缓存上进行绘图。将这个翻页过程一直持续下去,直到动画结束。
有了DirectDraw,整个翻页的任务并不是一件十分困难的工作。你既可以创建一个简单的双缓存翻页链结构(一个主页面和一个后台缓存),也可以创建一个使用起来更为灵活的多后台缓存翻页链结构。
由于DirectDraw更多的使用的是硬件的特性,使得翻页变得极为快速,这个过程在屏幕上不会产生丝毫的闪烁,其速度可以达到与显示器的刷新率一样的数量级。在后面的DirectDraw教程中,我们将具体介绍如何在DirectDraw程序中实现翻页。
10、矩形(Rectangle)
返回目录
在Windows编程中,屏幕上的对象都是以一个封闭矩形的形状出现的。一个封闭的矩形可以用两个点来确定,左上角和右下角。绝大多数应用程序使用RECT结构来定义一个封闭矩形,用于blit操作或碰撞检测(hit detection)。RECT结构定义如下:
typedef struct tagRECT {
LONG left; //矩形左上角的X坐标
LONG top; //矩形左上角的Y坐标
LONG right; //矩形右下角的X坐标
LONG bottom; //矩形右下角的Y坐标
} RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;
应该注意的是:这个矩形区域是排除边线的,并不包括它的右边线和下边线。所以,这个矩形的宽度应该等于right-left,而不是right-left+1;同理,矩形的高度等于bottom-top。
11、精灵动画(Sprite animation)
返回目录
精灵动画被广泛的用于多媒体及游戏软件中。从最基本的意义上说,精灵是一个可以在背景屏幕上四处移动的图象,通常,这个图象的形状是不规则的。它的实现方法可以简单的这样来描述:将精灵画在可见的背景页面上,然后将所画的上一个精灵从页面上抹去,再将精灵画在页面的另一个地方,依次类推。于是,对观察者来说,精灵在屏幕上就动起来了。
然而,在绝大多数情况下,我们所使用的精灵图象并不是规则的矩形,它们可能是多边形,也可能是一个支离破碎、完全不规则的图形。这就给我们实现精灵动画带来一个巨大的挑战,因为所有的blit函数所使用的都是规则的矩形区域,只有对于矩形区域,才能使blit操作更高效、流畅和便于调用。
于是,在GDI编程中,使用了一种称为屏蔽的方法,这也跟电影的特级合成用的方法差不多,先让一个人在一块蓝布前表演一些看上去很惊险的动作,然后再将这些影片与事先拍好的背景合成一体,有蓝布的地方成了背景的画面,人就好象置身其中了。
要在计算机中实现这样的动画,得有两幅图:一幅是精灵图(Sprite),一幅是屏蔽图(Mask:也称掩码图)。精灵图中使要显示的部分颜色保持不变,其余全为黑色,屏蔽图中使精灵的部分都为黑色,其余全为白色。
有了这两幅图,经过两次blit运算,就可以把想要的精灵贴到背景上去了。第一次blit是让屏蔽图与背景进行布尔“与”(光栅操作代码为SRCAND)运算,第二次让精灵图与背景进行“异或”(光栅操作代码为SRCINVERT)运算。
伪代码如下:
BitBlt( hDCdest, 0, 0, width, height, hDCMask, 0, 0, SRCAND );
BitBlt( hDCdest, 0, 0, width, height, hDCSprite, 0, 0, SRCINVERT);
- 可以看出,在GDI中实现精灵动画是个比较复杂的过程,主要原因就是因为GDI的Blt函数不支持透明方式。在下面我们将看到,在DirectDraw中,由于其blit函数支持关键色,可以实现透明blit,所以,与GDI相比,在DirectDraw中实现精灵动画要变得简单得多。
12、关键色(Color Key)
返回目录
DirectDraw的blit函数,支持带关键色(Color key)的透明blit操作。这就是说,如果在源页面上指定了一个颜色为关键色,那么在blit操作中,将视具有这种颜色的区域为透明,不会被传送到目标页面上。
所以,不管你的精灵看起来是否象一个矩形,你必须首先使它们可以放在一个合适大小的矩形区域内。然后在这个包含了精灵图象的矩形内,将不属于精灵图象的部分全部使用同一种颜色,或使其在一个颜色范围之内。这个颜色或颜色范围必须是精灵图象中所没有用到的,它就是关键色。
使用IDirectDrawSurface3::SetColorKey函数,将这个关键色设置给该页面。之后,调用IDirectDrawSurface3::Blt或IDirectDrawSurface3::BltFast函数,将该精灵blit到另一个页面上去,矩形区域中只有属于精灵的像素被映射了,其余带关键色的像素全被视为透明,对目标页面不会产生任何影响。这种在blit操作中,用于源页面表示透明区域的关键色称为源关键色(Source color key)。
除此之外,你还可以使用一种目标关键色,它所影响的只是目标页面。目标关键色定义了在blit操作中,目标页面上可以被覆盖的像素。举例来说,如果你要设计一个有一棵大树的背景,一个兔子在树后活动,当它经过树的时候,会被树遮住它的一部分或全部,以创造一种前后效果。那么,同样,你应该给背景页面上所有除了树的像素使用关键色,表示只有这些像素才能允许在blit中被使用。使用IDirectDrawSurface3::SetColorKey函数,将这个关键色设置给背景页面。然后调用IDirectDrawSurface3::Blt或IDirectDrawSurface3::BltFast函数并且指定了使用目标关键色,那么,当你把包含了兔子的页面blit到目标页面上大树所在的位置,大树总是完整的,兔子的某部分会被大树遮挡住,就象出现在树后一样,前后效果出现了。
13、补丁(Patching)
返回目录
在精灵动画的过程中,当你把精灵画到一个新的位置之前,你必须将上一个位置的精灵从背景上抹掉。当然,最简单的做法是莫过于重新刷新整个背景,使其还原,然后再将精灵画上去。但是,这样做会使你失去很多的时间,而时间对于动画来说是非常宝贵的,而且最主要的一点就是,你的屏幕会因为大面积的刷新而闪烁。所以,你应该跟踪精灵所在的上一个矩形位置,然后在画下一个精灵之前,只重画这一个区域。这种方法被形象的称为打“补丁”(patching)”。
要给精灵的上一个位置打上补丁,你必须在上一步绘制该精灵之前,把这个矩形区域的背景内容保存下来,在你要画下一个精灵之前,用这个补丁去还原这块区域。这个过程会进行得非常和谐,因为与刷新整个背景相比,它不会占用太多的时间。
打补丁的方法可以按以下几个步骤进行:
- 将保存的精灵的上一个位置的背景图象复制到背景上。
- 把将要绘制精灵的位置的背景图象保存下来。
- 将精灵blit到背景图象上。
- 重复步骤1
14、范围检查(Bounds Checking)与碰撞检测(Hit Detection)
返回目录
范围检查和碰撞检测是编程中与精灵动画相关联的两个重要任务。
范围检查用来限制精灵的可能的活动范围,例如,在程序中,你可能想让某一个精灵限制在屏幕的某个矩形区域内活动,要完成这一步,你应该在精灵每移动一步之前检查精灵所在的位置,使这个位置的坐标保持在一个矩形范围之内(通常是一个RECT结构),并且阻止精灵移出这个矩形区域。DirectDraw并没有提供范围检查的服务函数,但是你可以用很简单的程序实现这样一个功能。
碰撞检测,或称为冲突检测,用来判断某一时刻是否有多个精灵处于同一位置。大多数的碰撞检测是检查某个精灵的包络矩形是否与另一个精灵的包络矩形有重合部分。因为有太多种不同的方法来实现不同种类的碰撞检测,所以DirectDraw也没有为用户提供碰撞检测的服务函数。用户可以根据自己的需要编制碰撞检测的程序。