<<葵花宝典>>2000黄金版
翻译:SEVECOL
RLE Sprite指南 作者:Jonathan Griffiths(jpg@wave.co.nz)
介绍:
Sprite是游戏中最常用的一种元素,只在最近才被3D多边形引擎所超越.聪明的sprite系统将给游戏带来很大的帮助.这有一篇短文章介绍一个智能很高,且很有效率的RLESprite系统.
这里所讨论的sprite是指矩形的子位图,子位图中的一种任意的颜色可被定义成透明的.当渲染sprite到屏幕上的时候,被定义为透明色的象素并不绘出.sprite在场景的上面就产生了上面的效果.
RLE Sprite是一种使向屏幕绘图高效和节省内存的保存sprite的方法.下面 的讨论将说明如何实现基于RLE Sprite的引擎.*任何的代码都是用C写的.其中有一些用到了JLib(一个可移植的图像库.),他们能很容易的改到别的图像库.这些文档都是我用JLib和我对于RLE Sprite的经验编写的.您能够检查代码的完整性.剪贴下来能够编译.*JLib能够在下面找到:
ftp://x2ftp.oulu.fi/pub/msdos/programing/djgpp2/jlib_X-X.zip;
您应该用不成比例的字体阅读文档中的图表,否则ASCII图表将会混乱.
简单的Sprite:
让我们从简单的sprite开始.最简单的sprite系统是用一个2维数组来储存 sprite中每
一个点的颜色.一个太空船的sprite看上去会是下面的样子:
XXXXXXXXXXXXXXXX
XXXXXXX XXXXXXX
XXXXXXX XXXXXXX
XXXXXX XXXXXX
XXXXX XXXXX 'X' = 颜色值0 (在本例中是黑的)
XXXX XXXX XXXX ' ' = 其他的颜色 (Say Green)
XXX XXXX XXX
XXX X X XXX
XXX X X XXX
XXX XXXX XXX
XXX XXX
XX X X XX
X XX XX X
XXXXXXXXXXXXXXXX 一个15X14 Cheesy太空船sprite.*
假如您用这太空船做sprite,您应当创建一个15X14的数组,并且按上面的图片颜色填充他,如下:
#define SHIP_WIDTH 15
#define SHIP_HEIGHT 14
unsigned char ship_sprite[SHIP_WIDTH*SHIP_HEIGHT]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
...
}
您可一用以下的代码来绘制sprite:
int x,y;
int xpos,ypos;
...
for (y = 0; y < SHIP_HEIGHT; y ) /*图像的每一行*/
for (x = 0; x < SHIP_HEIGHT; x ) /*这行上的每一个象素*/
if (ship_sprite[y*SHIP_HEIGHT x] != 0) /*透明?*/
draw_point(xpos x,ypos y,ship_sprite[y*SHIP_HEIGHT x]);
我们画了sprite中的每一象素,假如像素不透明,我们就画他.检查是不是0要快于其他值,所以我们把透明色设为0.
用着种方法能够画任意的sprite,还能检查点是否在屏幕中,但他很慢,不是个好方法.
第一个问题是您必须去检查每一个像素,看看他是否是透明色,不是便画他.
*让我们跳到理论的大陆一会儿,思考理论上画sprite的速度极限.我们选一个接近他的算法.
画sprite最快的方法是不检查任何一个像素,并且能正确的画在屏幕上,我们一个接一个的画需要画的像素,然后停止.您没有浪费时间在循环和比较上.有一种方法能象上面所说的相同,我们称他为编辑了的sprite.
编辑了的sprite实际上是程式,如下:
void draw_spaceship(int x, int y)
{
/* these commands draw the sprites solid pixels */
draw_point(x 20,y 20,1);
draw_point(x 21,y 20,2);
draw_point(x 22,y 20,2);
draw_point(x 23,y 20,1);
...
}
*第二个问题是这方法是困难的和危险的.并且不能移植到任何的电脑上.
然而这方法给了我们对于怎么样才能更快的画出sprite在屏幕上很大的启示.我们应该想办法去排除检查象素,只画不透明的像素.
进入RLE Sprite
RLE是Run Length Encoding.是一种简单的压缩重复数据的方法.他提供了很好的压缩/解码时间比.
RLE用很短的代码代替重复的数据.上面的例子:
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,
用RLE压缩为:
(22 0's),(2 1's),(13 0's),(2 1's),(6 0's)
RLE要源文档有很多重复数据才能得到很好的效果,假如源文档很少甚至没有重复,那用RLE压缩后可能比源文档还大.
我们选用RLE来保存sprite,他能够很容易的实现忽略透明的像素,我们再也不要检查每一个像素在我们画他们之前.让我们看看如何实现RLE Sprite
首先,我们用RLE编码来保存sprite,然后:
我们的RLE代码不要保存任何数据,只保存信息.如下:
0,0,0,0,0,0,3,3,3,5,6,0,0,0,0,0
我们保存为:(blank 6),(solid 5),(blank 5)
当我们解释我们的RLE代码时,我们得到每个像素的确切值从原始的数据中,我们要开始一个新的RLE序列对应sprite的每一行.(这能帮助我们用裁剪,下面会讨论)
我们能够通过下面的代码画出sprite的一行:
while 代码没结束得到下一个值
if 值 is blank
skip count pixels
else
draw count pixels
end
end
代码和RLE有所不同,第一个代码我用了两个字节:is_solid,length.假如is_solid是0,则是连续lenght个blank,否则是连续个颜色.我更有个更好的代码,他不用判断是否为blank.
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!




