序
这节讲述的是HoHo的2D模块最重要的功能,不用我多说,这就是HoHo的图像绘制部分,相信没人会否认图像绘制对于游戏的重要性,基本上游戏给玩家的表述多是用图像来说明,HoHo提供了多种多样的图像绘制方式,同时在性能方面也有相当的表现。
一般在游戏中常用的绘图方式有4种:普通绘制、颜色键(ColorKey)绘制、Alpha混合绘制、色彩饱和(Additive)绘制,其中普通绘制和颜色键(ColorKey)绘制在DirectDraw中就有支持,Alpha和Additive则需要我们自己进行运算处理(这里Alpha混合绘制和色彩饱和(Additive)绘制简称为Alpha和Additive),不过没关系,这些运算以及处理工作HoHo已经为你完成,你需要知道的就只是如何去使用。
目录: 普通绘制 颜色键(ColorKey)绘制 Alpha混合绘制 色彩饱和(Additive)绘制 图像RECT裁减绘制
普通绘制
普通绘图非常简单,只要是HoHo载入的图像数据都可以用来直接普通绘制,普通绘制就是将图像原貌反映在屏幕上,只用通过以下简单的一句代码就可以完成,代码片段:
GetGraphics()->DrawBitmapMMX( 100, 100, g_pBitmapBMP, SCREENBUFFER );
普通绘制
|
![]()
| 这样就行了,是不是很简单?这里还需要说明一下SCREENBUFFER的功能目的,SCREENBUFFER实际上也就是一个LP_BITMAPX数据,只不过它比较特殊,它被HoHo默认创建,并且作为与DirectDraw接口进行图像数据更新的一个通讯图像数据,我们只需要知道把图像绘制到它上面就OK了。
可能有人会问,我们这里的绘制是从g_pBitmapBMP到SCREENBUFFER,我们能否倒置?答案是肯定的,如果你把他们的位置倒换,那么就变成SCREENBUFFER的数据被绘制到g_pBitmapBMP中,除了SCREENBUFFER外,只要是常规的LP_BITMAPX数据结构都可以进行此项操作,有些特殊的LP_BITMAPX结构是无法互通数据,这里我们留着后面再来介绍,将图像绘制出来是此节的主要讨论内容。
颜色键(ColorKey)绘制
游戏中不可能所有的图像都是整块并且标准的四边形图像,比如游戏中的人物(精灵),它们在图形文件中所存储的数据如下:
人物(精灵)原图
|
![]()
| 如果我们按照普通绘制的方法,那么非人物(精灵)的图像数据部分也会被绘制到屏幕上,令人厌恶的紫色色块也会进入我们的游戏视野,我们来看看如何将这些紫色部分去掉,不要让它来影响我们游戏的视觉效果。(通常我们不需要的颜色称之为颜色键(ColorKey))
HoHo中可以直接进行ColorKey的过滤处理,不过在HoHo对图像绘制进行ColorKey过滤的时候,我们必须事先通知HoHo,什么颜色是ColorKey,看看如下代码片段:
g_pBitmapBMP->SetColorKey( RGB2Hi(255,0,255) );
设置ColorKey
|
![]()
| 这里我们用到了两支函数,其中SetColorKey()就不用多说了,它就是用来设置LP_BITMAPX的ColorKey,它需要的是一个 PIXEL结构的数值,PIXEL是一个16Bit的数值,不要问我为什么是16Bit,我只能回答你,因为我们的游戏是在16Bit模式下运行的;另外,让我们看看RGB2Hi(),这是一支HoHo提供的全局函数,功能是将RGB颜色值转换为上面我们所说的16Bit的PIXEL数据,这里我们用 RGB=255,0,255(紫色)来作为ColorKey的设置参数。
再我们进行图像绘制之前,我需要说明一下,HoHo内部默认的ColorKey是RGB=0,0,0,可能有人会反对这样的做法,毕竟RGB= 0,0,0就是黑色,黑色在游戏图像中出现的几率还是相当频繁,用黑色岂不是很不方便,用RGB=255,0,255来作为默认ColorKey不更好?我只能说请相信我,我这样做肯定有其好处,虽然这个好处未必明显;在SetColorKey()函数执行后,原来LP_BITMAPX的图像数据中的黑色 (RGB=0,0,0)部分均会被假黑色代替(RGB=0,0,1),所以上面我们设置紫色为ColorKey,HoHo会将原图像中的紫色部分改变为黑色,而原来的黑色部分会被修正为假黑色。(如果你不明白这段文字所说的问题,请掠过此段继续看后面)
说了那么久,在我们设置好ColorKey之后,我们可以同样通过DrawBitmapMMX()函数来进行ColorKey处理的图像绘制,代码示例如下:
GetGraphics()->DrawBitmapMMX( 250, 100, g_pBitmapBMP, SCREENBUFFER, true );
ColorKey图像绘制
|
![]()
| 在这里我们只是简单的在函数后面加了一个true标记,此标记告诉HoHo,此图像要进行ColorKey处理。
Alpha混合绘制
前面两种绘制方式是游戏中最基本的应用,现在我们来看看Alpha混合如何处理,Alpha混合处理可以给游戏带来非常多的特效以及更好的视觉效果,在 HoHo中,Alpha混合的算法以及优化等工作都已经帮你完成,你所需要的就是简单的调用函数就可以轻松实现Alpha的混合处理,我们来看看一下的代码片段:
GetGraphics()->DrawBitmapAlphaMMX( 400, 100, g_pBitmapBMP, SCREENBUFFER, 16 );
Alpha混合绘制
|
![]()
| 我们看看它最后的一个参数,16这个数值是通知HoHo进行16阶Alpha混合,这个参数的取值范围为0~32,16相当于是50%的混合;为什么取值范围那么小?为什么不是0~255?这是因为我们所用的图形模式是16Bit色彩,它所变换出来的色彩表现能力实际上最后只能得到0~32级的变化。
注意:Alpha混合操作的函数会自动进行ColorKey的过滤处理。
说到Alpha混合绘制,这里还需要介绍一下Alpha通道混合处理,HoHo支持的TGA图形Alpha通道数据,并且可以根据通道数据来进行处理,可能有些朋友对Alpha通道图不是很了解,这里我们简单的说说Alpha通道的作用。
上面说的DrawBitmapAlphaMMX()可以对图像进行Alpha混合处理,但是有些时候我们需要的是图像的局部Alpha混合,或者是一张图片中不同的区域有不同的混合方法,如果这样的话,上面这支函数就无法达到,这时候就需要借助Alpha通道数据来协助图像的绘制。
在Lesson3中,我们载入了一张TGA带通道的图像数据,这里我们可以通过以下方法来进行绘制,代码片段如下:
GetGraphics()->DrawBitmapAlphaChannelMMX( 300, 300, g_pBitmapTGA, SCREENBUFFER );
Alpha通道混合绘制
|
![]()
| 这样我们就可以把图像数据中的通道数据应用起来。
还有一种情况,我们需要对带有Alpha通道的图像在加入Alpha值的处理,这时候只要在最末尾处加入一个Alpha混合值就行,就如同DrawBitmapAlphaMMX()的使用。
色彩饱和(Additive)绘制
现在的游戏里面到处都是光影特效,比如武士飞舞大刀所带的刀光、法师施展的绚丽魔法等,这些都可以通过色彩饱和运算来实现,我们必须先来了解一下色彩饱和的处理方式,色彩饱和是将两张图像的数据融合起来,如果图像是黑色,则两张图像融合后还是原来的图像,当然,这样说可能不是很明了,可以看看本章节最后的附图,不过在看附图之前,我们来看看代码的实现:
GetGraphics()->DrawBitmapAdditiveMMX( 550, 100, g_pBitmapBMP, SCREENBUFFER );
色彩饱和(Additive)混合
|
![]()
| 由于色彩饱和混合的特殊性,它不需要进行ColorKey处理,也不需要Alpha值的参数,就如普通绘图一样。
图像RECT裁减绘制
有时候我们载入了一张很大的图像,但我们在绘制过程中,我们只需要绘制其中的某个小区域,如果我们整张图进行绘制,那么将是极大的浪费资源,HoHo 已经为你准备了这方面的处理;用过DirectDraw表面绘图的朋友肯定知道DDraw在绘图的时候需要一个RECT参数来进行绘制区域的确定操作,同样,你也可以传入一个RECT结构参数来确定你所需要的绘制区域,看看一下代码片段:
RECT rect = { 0, 0, 32, 48 };
GetGraphics()->DrawBitmapMMX( 700, 100, g_pBitmapBMP, SCREENBUFFER, &rect ); GetGraphics()->DrawBitmapMMX( 750, 100, g_pBitmapBMP, SCREENBUFFER, &rect, true ); GetGraphics()->DrawBitmapAlphaMMX( 700, 160, g_pBitmapBMP, SCREENBUFFER, &rect, 16 ); GetGraphics()->DrawBitmapAdditiveMMX( 750, 160, g_pBitmapBMP, SCREENBUFFER, &rect );
RECT裁减绘制
|
![]()
| 这里我们制定绘制g_pBitmapBMP图像中的起点(0,0)至终点(32,48)位置的图像,仔细看,这些绘制函数不就是我们上面所介绍的函数,没错,在HoHo中有这些函数的重载操作,只要是第五个参数传入了RECT结构数据,那么HoHo就会根据RECT所制定的位置来进行绘制,当然,具体要进行如何的绘制方法就如同原函数的效果。
最后,我们看看今天的游戏程序运行结果:
![]() (图像资源来源于 金点时空 的《圣剑英雄传II》)
|
|
|
游戏程式设计指南(HoHo篇)Lesson 5 — 字体绘制篇
|
|
序
图像作为游戏的主要输出途径,其中不可或缺的就是文字,不管是作为游戏中使用,或者作为我们程式的调试手段,文字的输出表示是相当重要的,本节就是要给大家介绍如何在HoHo游戏程序中绘制文字;HoHo为大家提供了两种绘制方式,一种是通过Windows的GDI来进行文字绘制,另外一种则是通过 HoHo自己的处理方式来进行文字绘制,当然,HoHo自处理的方式在性能方面比GDI的处理方式高出许多,同时,HoHo也提供了一个字体生成器,可以很方面的制作我们有戏当中所需要的字体格式。
注:HoHo的自处理字体目前只支持等宽高的字体。
目录: 使用GDI绘制文字 使用HoHo自处理文字 HoHo字体生成器使用
使用GDI绘制文字
首先,我们来看看如何使用Windows的GDI来进行文字绘制,大家都知道,Windows为我们提供了强大的文字绘制功能,很幸运的是, DirectDraw继承了这些,在DirectDraw的表面(Surfce)可以看作一个可供系统GDI绘制的缓存,当然,这里我们不会深入说明如何处理,HoHo已经把这些东西封装好了,好了,让我们来看看如何使用。
第一步初始化,不用多说,声明操作句柄,代码片断如下:
HFONT g_hFont = NULL;
声明GDI字体句柄
|
| 声明完之后,我们必须对它进行初始化操作,我们通过调用系统API函数来进行Windows字体句柄创建,代码片断如下:
g_hFont = CreateFont(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "宋体");
初始化GDI字体
|
| 我们可以看到,这里我们创建了一个12点阵的字体大小,当然,这些复杂的参数在MSDN可以查询到,这部分数据Windows的操作部分,我们不对此进行深入说明,有兴趣的朋友请参看MSDN。
创建好GDI字体后,我们可以通过调用HoHo的图形函数DrawText()来进行字体绘制,代码示例如下:
GetGraphics()->DrawText( SCREENBUFFER, 30, 30, g_hFont, "GDI字体 Test 测试", RGB2Hi(255,255,255) );
绘制GDI字体
|
| 这样就能完成GDI字体的绘制工作,很easy吧!:)
补充说一下,由于GDI字体绘制的机制与HoHo有所差别,故此函数在实际应用中操作比较消耗速度性能。
使用HoHo自处理文字
接下来让我们看看HoHo自处理字体的使用,为什么要使用HoHo的自处理字体?因为它能够给你带来绘制效率,同时可以给你带来字体的附加效果,如:字体的边缘Alpha混合等。
HoHo字体的初始化和GDI字体一样,我们首先声明操作句柄,代码片段如下:
LP_FONT g_pHoHoFont = NULL;
HoHo字体声明
|
| 声明完后,我们一样进行字体设备的创建,不过不同于GDI的是,HoHo字体是从自己的字体库文件中提取出来,而并非来源于Windows系统,这样就能有效的避免不同Windows导致的字体错乱情况,这个情况在繁体版本和简体版本的Windows中尤为明显。让我们看看创建HoHo字体的代码片段:
g_pHoHoFont = msCreateFont( "Font12.dat" );
HoHo字体的创建
|
| 就这么简单的一句就能将字体从字库文件中创建出来,接下来我们看看如何绘制,代码片段如下:
GetGraphics()->DrawFont( SCREENBUFFER, 30, 60, g_pHoHoFont, RGB2Hi(255,255,255), "HOHO字体 Test 测试" );
HoHo字体绘制
|
| 看看,是不是和GDI的字体绘制方式类似,问题就那么简单。
我们看看我们程序的执行结果:
![]()
看到HoHo字体还带着轮廓线了吗?这个就是HoHo自处理字体的功能,只要字库保存了轮廓线数据,我们的字体就能进行轮廓线绘制,当然还能进行轮廓Alpha处理,这里我简要的说明下一一些关于HoHo自处理字体的参数,看看字体的结构:
struct HOHO_API tagFont { int nStyle; // 字体风格 int nWidth, nHeight; // 字体宽高 int nASCIIWidth; // ASCII宽 int nASCIISize; // ASCII码的Size int nGBSize; // GB码的Size BYTE* pFontData; // 汉字起始地址 BYTE* pASCIIData; // ASCII起始地址 char strFontName[32]; // 字体文件名 long lType; // 字体类型 int nLength; // 字体文件长度 int nSpace; // 字间距 int nAlpha; // 是否使用Alpha混合 int nAlphaLevel; // 混合程度 int nAlphaEdge; // 是否使用Alpha边缘混合 int nAlphaEdgeLevel; // 边缘混合程度 unsigned short pixelEdgeColor; // 边缘线色彩 };
typedef tagFont* LP_FONT;
这个就是HoHo的字体数据结构,其中红色注释部分为用户可修改部分,只要进行相应的修改,则HoHo会根据修改的内容进行绘制,同时,也可以通过其他的数据来了解当前字体的宽高等信息。
对了,游戏程序结束前记得对HoHo自处理字体进行释放,代码片断如下:
msReleaseFont( g_pHoHoFont );
HoHo字体生成器使用
上面介绍了HoHo字体的使用,那么我们如何创建我们所需要的字体呢?很简单,HoHo已经为你准备好了字体制作工具,只要轻轻的点击几下鼠标就能搞定,看看字体转换工具的界面:
![]()
只要选择好所需要的字体,然后选择字体大小,最后点一下保存即可,如果把“轮廓线”的复选框选上,则会在创建的自体上添加轮廓线。
此工具附带源码,可以在HoHo的包中Tools文件夹里找到,有兴趣的朋友可以研究一下。
|
|
|