我经常说,我们以前玩过的很多游戏虽然看上去是 2D 的,但其实是 3D 游戏——比如热血物语、双截龙系列,它们具有一套三维的立体空间逻辑,从而不再使得游戏的舞台限制在只有左右移动和上下跳跃这两种轴向——拥有三个维度极为自由开放的移动范围相信也给很多玩家留下了深刻的印象,在上次的文章里,我们已经介绍了这种游戏的物理部分简单实现,本次将会聊到这类游戏在渲染上的重要技巧。
显然,在用 2D 精灵模拟的 3D 空间里,任何一个物体都不简单:如图所示的一个立方体,具有一个 oblique 视角(或者,我们叫 cabinet 视角更准确)的造型。这样的视角下,如果有另外一个精灵和它相互遮挡,应该怎么处理它们的渲染顺序关系呢?
注:为了简化描述,本文章的 3D 空间假设所有物件的 z 坐标都相同,即“没有和地面的高度差”。
任意两个物体之间的排序
按照我们一般的简单思路(比如在经典的 topdown 视角下,如 RPGMAKER 系列),谁在世界上具有较大的 y 值,谁就靠近屏幕,谁就应该更靠后地渲染,对吧?不过在这样的视角下,就没有那么简单了,来看一个例子:
如图,根据十字形标记,我们可以轻松地发现 shari 的 y 坐标小于立方体的坐标,所以她理应被挡在立方体的后面(先于立方体渲染),对吧?可是当她来到另外一侧的时候,情况就变化了:
如图,shari 的 y 坐标依旧小于立方体的 y 坐标,但这个位置上,我们是希望 shari 遮挡立方体而不是被立方体遮挡的,所以我们需要考虑到更多的情况。
显然,这个世界里的任何一个物体都应该携带它的"底座"信息。如图,红色的平行四边形就是上面立方体的"底座"信息,而绿色是它的高度信息(如果你需要一些更细致的排序,比如算上 z 轴,本文暂不讨论)有了这个信息,我们就可以确定任意两个对象之间的绘制顺序。
我们把两个要排序的物体分别命名为 A 和 B,A 底座的上边缘称为 aTop,下边缘称为 aBottom;B 底座的上边缘称为 bTop,下边缘称为 bBottom。
aBottom 的 y 坐标小于 bTop 的 y 坐标:
这时候 A 显然是在 B 的后方,也就是 A 先于 B 渲染。
aTop 的 y 坐标大于 bBottom 的y 坐标:
这时候 A 显然是在 B 的前方,也就是 B 先于 A 渲染。
其它的情况:
由于我们这里的视角下,侧面是一个 45 度的斜线,所以我们可以很轻松地把两个物体下边缘的 y 轴距离加到 aBottom 的右端点去进行判断,像是这样: