原文地址: http://twinklebeardev.blogspot.com/2012/08/lesson-5-clipping-sprite-sheets.html
在基于精灵的游戏中,通常会使用一幅包含了许多小图的大图——比如说使用包含tile的tile集,而不是一个tile就是一张独立的图片。这种图像的类型被称作精灵表(sprite sheet,我不能确定我这么翻译是否恰当——译注)。这种方式很有用,因为这样做我们的游戏就用不着每幅图像都用一个独立的文件来存储,而直接绘制表中我们需要的一部分就好了。
译注:我不确定看这篇文章的初学者们——仅针对初学者们——是否理解诸如精灵(Sprite)、tile之类词语的含义。在2D游戏中,精灵大概就是2D游戏中能够移动来移动去的图块;至于tile,它大概算是精灵的子集,它的中文名称本来是瓦片,一般我们可以看到很多2D游戏的场景是由很多相同的图块拼出来的,那一块一块儿的玩意儿就是tile.欲纠结此问题请看维基百科Sprite_(computer_graphics)词条……= =
本节中我们将学习怎样使用一个简单的精灵表以及怎样指定精灵表中我们需要的子集,也就是绘制时的裁剪。本节的精灵表是一幅有四个圆形的简单图像。
在一个精灵表中,图像被分割成了一些我们能够裁剪的基础图形。在这个表中呢,每个圆形都处于一个100x100的矩形中,这样我们就可以单独绘制它们而不是绘制整个图像。
本节的代码都是基于第四节中的代码的。如果你没有学完第四节,你需要回头去看。如果你已经知道了第四节所涵盖的内容,从github上拉取代码后,我们立刻开始。
通过上一节提到的ApplySurface函数,你可以发现最后传给SDL_RenderCopy一个NULL。
而这个参数就是源矩形(rect),被称为clip(裁剪),它指定了需要绘制的图像中的一个子矩形——或者说,它指定了裁剪的位置,宽度,还有高度。为了给源图像传递一个clip,我们需要给ApplySurface函数增加一个clip参数。
但如果我们有一幅图像,我们想要把它全部绘制出来呢?用不着强迫我们自己传一个整张图片的clip过去,我们只需要指定一个默认的参数并且检测什么时候获得了这个参数就够了。我们要把clip参数当作SDL_Rect类型的指针,并把它的默认值设为NULL。通过这种方式,如果没有clip传入,我们仍可以把该参数传入RenderCopy。结果会是和当我们直接传NULL时一样,绘制整张图。
我们还想给我们的函数添加另外一样东西:
惯例,我们使用LoadImage函数来加载图像。
我们现在需要准备好我们的裁剪矩形,把它们存储在一个数组里面。为了避免手动输入所有的裁剪数据的繁琐,我们可以充分使用在生成图像的时候自动循环生成裁剪矩形的方法。如果你完成了第二节中的extra challenge,这个方法对你来说会更容易上手一点。
首先我们指定每一次裁剪的宽和高,在本例中我们制定为100x100,并且定义一个存储四个SDL_Rect的数组。然后我们创建一个for循环还有一个计数器来适当地设置每次裁剪的坐标。
如果你没有完成第二节的extra challenge或者你觉得这有点困难,我来解释一下这是怎样运作的。我们想要创建四次裁剪,所以我们for循环了四次,从0到3以匹配数组的下标。我们还需要把当前正在使用的列数保存下来,以便于正确地设置裁剪时的x坐标。从第0列开始向右移动,经过第三次裁剪,也就是从0开始遇到的i%2 == 0的时候列数增加.我们还需要确认当开始第一次裁剪的时候我们是位于第0列的,由于0%2结果也是0,所以我们设置了一个条件判断来忽略这种情况。
现在我们想要计算裁剪时的x和y坐标。我们需要在每次经过一列的时候给x坐标增加一个图片宽度的距离,每次经过一行的时候给y坐标增加一个图片高度的距离。x坐标的设置应该很清楚,我们可以直接设为tile的宽度*列数。y坐标的设置需要使用我们使用当前的循环迭代数与每列裁剪的个数来确认它的像素位置。宽度和高度对于所有的裁剪来说都是均匀的,所以我们可以直接设好它们而不需要多余的计算。
于是,当我们运行这个循环的时候,我们会创建四个裁剪,每个裁剪会获取其对应的子矩形的坐标。你还不明白它是怎么回事吗?试着在你脑中运行这个循环,并计算列数以及每次迭代的x与y坐标,然后看看它们在精灵表中是怎样排列的吧。
最后一步是设置一个让我们知道我们想要绘制的究竟是哪一个裁剪的值,在这里,它就是一个对应于裁剪数组下标的值。我们先把它设为第0个裁剪。
在开始主循环之前,我们还需要设置图像的绘制坐标。我选择使用和上一节同样的方法计算出图像的中间坐标。我们还想创建一个bool类型的退出变量以及一个SDL_Event.
为了确认我们的裁剪正确设置并且正确显示了,我们想要单独绘制每一个裁剪。为了做到这一点,我们可以设置一些时间轮训,以此来改变useClip的值,以便于我们可以绘制每一个clip。
这里我们检查了输入类型是否是一个按键消息,然后在key上使用了switch语句,来选择适当的响应。
绘制部分的最后,我们清屏,将裁剪的值传入ApplySurface函数。
最后将renderer呈现出来,让它显示出结果。
当你运行这个程序的时候,你可以按键盘上的1-4键,然后可以看到不同颜色的圆被单独地绘制到了屏幕上!
End of Lesson 5
感谢加入!我们第六节:使用SDL_ttf绘制True type字体见!