![](http://articles.gameres.com/Program/Abstract/Thinking/x45panduan_1.gif)
当然这有需要一点点投机取巧的方法。如图,在斜视角游戏里,每个物体都被包含在一个六面体中(左图左上角部分),我们取一下巧,就是这个六面体的单位高度,投影到我们这个游戏平面上恰好是Tile的高度,那么这个单位体积的六面体画上去就是左图左上角的这么一个六边形,很规则吧!这个六边形所挡住的部分就是这个单位高度物体所遮挡的范围。按照我们前一次说过的Tile排列方法(见下图,把图再贴一遍吧!),设这个立方体所处的坐标是[2,2],这个立方体所挡住的3个Tile的坐标[1, 1],[1, 2]和[1,3](这时我们的Tile排列方法显出了一点儿弊病,如果立方体的坐标是[2,3],那么被挡的3个Tile坐标就是[2, 2],[1, 3]和[2,4],就是说有了奇偶的区别——虽然在Tile的位置判断上有一点点优势。谁能给出个更好的排列方法?)。如果精灵(就是运动的物体)走到了这几个地方,就有可能被挡住,这时就需要画完精灵后再重画前方的物体了。
![](http://articles.gameres.com/Program/Abstract/Thinking/x45chubu_2.gif)
这只是单位高度的物体,如果物体的高度是2个单位(就像左图右上角的部分),仍假设物体的坐标是[2,2](记住还是有奇偶的区别的),那么它挡住的Tile就是[1, 1],[1,2],[1, 3],[0, 1],[0, 2]和[0,3]。如果物体占的范围比较大(就像左图下方的部分),假设该物体坐标是[2,1]和[1, 2],那么所挡住的坐标就是[2, 0],[1, 1],[1, 2]和[1,3],也就是[2, 1]和[1, 2]所挡部分的并集。
如果还需要再进一步减少重画的范围,这就涉及到裁减一类的操作。我也比较讨厌这种繁琐的东西,其实原理并不复杂,大家看看图形学就明白了。
这一次就到这里,下次再见。
斜视角游戏中遮挡的判断(续)
上次说到了斜视角游戏的遮挡判断是靠物体的单位高度来判断的,原理是这样的,但实际按照这样做好像稍稍麻烦了一点——人物每走一步,都要费好大劲去找当前能够在屏幕上显示出来的所有物体,挨个去判断——美工倒无所谓,只是苦了编程的了,还要搭上宝贵的CPU时间。
那么怎么样才能让这个不得不做的步骤方便一点快一点呢?有一个简单的方法——就是地图的预处理。实际这也是个要麻烦编程人员的活动,就是在做地图编辑器时,生成地图的时候要对地图数据做一些为我们判断人物遮挡起简化作用的处理工作,在实际游戏的时候节省一点CPU时间而已。
我们先来定义一下地图数据的部分格式。(注:并不是一定要这样定义,这里只是提供一个思路,大家来探讨一下。)
我们可以在数据结构中加入一段Bit(之所以说是一段Bit,是因为我现在并不知道到底需要多少个Bit就足够用了)来说明地图Tile的遮挡高度属性,这一段Bit就是我们要讨论到的为了判断遮挡所需要预处理的数据。
我们来看一下左边的这张示意图。这张图的中间是一个底边为3x3个单位,高度为3个单位的物体,它所挡住的部分总共有21个Tile(其中垂直边上的6个Tile只被挡住了一半)。Tile上标注的数字就是这个Tile的遮挡高度,实际就是物体高度减去Tile距离物体底边的距离。所谓遮挡高度,就是说位于这个Tile上的物体所被遮挡的高度。好像还是不大明白,举个例子就清楚多了。比如说,一个高度为2个单位的人站在某一块Tile上面,假设这个Tile的遮挡高度大于等于2,那么就是说,这个人被完全挡住了,这个人实际在屏幕上已经消失了,不用再费劲去画这个人了。如果这个Tile的遮挡高度小于2,就是说这个人只被挡住了一部分,我们既要画这个人,又要费点劲儿去画挡住它的这个东西。
好了,现在有个小问题了,垂直边上6个Tile怎么办?无论多高的东西,都有可能在这露一小脸。但这个地方又跟周围没被挡住的Tile(绿色的)不同:其他没有被遮挡的Tile,人站在上面只需要画人就可以了,用不着去找有哪个物体挡住他,不用考虑重画的问题;而这些半蓝半绿的Tile,又是有一半是被挡住的,是需要重画的。那么,这就需要特殊情况特殊对待,再拿出一个Bit来记录该Tile是否有遮挡属性,不然就干脆把遮挡高度成员设为全1,把这种情况作为无遮挡属性处理,这样可以省下一个Bit,放到其他有用的地方去。这就要看游戏里最高的物体被定义成多高了(如果一堵城墙被画成上百个单位高度,那这一屏处理起来就方便得多了——什么都不用重画就行了)。
还有个问题,如果一个物体中间有洞怎么办?譬如说,一株枝桠横生的枯树,人走在枝桠的阴影里肯定会露出一些身体来的,这就要把这些Tile的遮挡属性设成和那种垂直边的Tile一样,这样就OK了。不过这可就要苦了那些做地图编辑器的程序员了,他们在产生地图数据的时候,就要从透明色来判断,哪个Tile该被设置成哪一种遮挡属性——因为物体并不都是这么方方正正的,比如一棵树就是底下小上面大的。
以上讨论的都是实心的物体,这种比较简单(看到斜视角的麻烦了吧,上面这么麻烦还是算是简单的)。我们再接着讨论另外一种情况——空心的物体。空心的物体,不是说盒子坛子一类东西,实际就是一些中间可以站人,而且还能露出人来的东西,比如说:一座凉亭。凉亭凉亭,四面透风之屋舍也,人可以站在中间,这样人就挡住了后面的柱子围栏,同时又被前面的柱子围栏和头顶的亭顶所遮挡。现在上面的方法都不适用了,不是么?前面讨论的东西没有那种既挡人又被挡的情况,这可怎么办?
哈哈,我来告诉程序员们一个好消息,这种情况让我们交给美工去处理吧!(谁让我是写程序的,我不想让我自己扛上这么多麻烦事,偷个懒美工们没意见吧!)这种情况下,为简便起见,我们把一个物体分解成几个物体来处理。简单一点,以一个城门示例,就不用凉亭了——没办法,谁让我美术功底矬呢,不过就是说明个意思(城门也算是个空心物体,人可以在里面穿行的),大家明白就可以了。看右图,一个空心的物体可以分成几个(在这里是两个)实心的物体,对于每个单独的实心物体,其遮挡原则和上面的一样,就是又变得这一部分是可以挡住在里面穿行的人的,左边那一部分对于穿行的人来说就是背景。凉亭和城门原则上说是一样的,就是分得在细一点而已,可能是四块或这是六块,就要看这个凉亭又几个出口了。这样一来,这个问题就容易解决了,只是要求美工要把接缝的地方做的完美一些。另外,写地图编辑器的程序员们,为了方便起见,在做地图编辑的时候,这类物体最好还是作为一个物体处理,不过实际上是几个子物体的集合,不然让别人去一点一点的对接缝有点儿太说不过去了,这一点要注意。