【干货】制作 oblique/cabinet 投影的 2D 游戏时,确认精灵先后顺序的排序方法

原标题:【干货】制作oblique/cabinet投影的2D游戏时 , 确认精灵先后顺序的排序方法

【干货】制作 oblique/cabinet 投影的 2D 游戏时,确认精灵先后顺序的排序方法
文章图片
我经常说 , 我们以前玩过的很多游戏虽然看上去是2D的 , 但其实是3D游戏——比如热血物语、双截龙系列 , 它们具有一套三维的立体空间逻辑 , 从而不再使得游戏的舞台限制在只有左右移动和上下跳跃这两种轴向——拥有三个维度极为自由开放的移动范围相信也给很多玩家留下了深刻的印象 , 在上次的文章里 , 我们已经介绍了这种游戏的物理部分简单实现 , 本次将会聊到这类游戏在渲染上的重要技巧 。

【干货】制作 oblique/cabinet 投影的 2D 游戏时,确认精灵先后顺序的排序方法
文章图片
显然 , 在用2D精灵模拟的3D空间里 , 任何一个物体都不简单:如图所示的一个立方体 , 具有一个oblique视角(或者 , 我们叫cabinet视角更准确)的造型 。 这样的视角下 , 如果有另外一个精灵和它相互遮挡 , 应该怎么处理它们的渲染顺序关系呢?
注:为了简化描述 , 本文章的3D空间假设所有物件的z坐标都相同 , 即“没有和地面的高度差” 。
任意两个物体之间的排序
按照我们一般的简单思路(比如在经典的topdown视角下 , 如RPGMAKER系列) , 谁在世界上具有较大的y值 , 谁就靠近屏幕 , 谁就应该更靠后地渲染 , 对吧?不过在这样的视角下 , 就没有那么简单了 , 来看一个例子:

【干货】制作 oblique/cabinet 投影的 2D 游戏时,确认精灵先后顺序的排序方法
文章图片
如图 , 根据十字形标记 , 我们可以轻松地发现shari的y坐标小于立方体的坐标 , 所以她理应被挡在立方体的后面(先于立方体渲染) , 对吧?可是当她来到另外一侧的时候 , 情况就变化了:

【干货】制作 oblique/cabinet 投影的 2D 游戏时,确认精灵先后顺序的排序方法
文章图片
【干货】制作 oblique/cabinet 投影的 2D 游戏时,确认精灵先后顺序的排序方法】如图 , shari的y坐标仍然小于立方体的y坐标 , 但这个位置上 , 我们是希望shari遮挡立方体而不是被立方体遮挡的 , 所以我们需要考虑到更多的情况 。

【干货】制作 oblique/cabinet 投影的 2D 游戏时,确认精灵先后顺序的排序方法
文章图片
显然 , 这个世界里的任何一个物体都应该携带它的"底座"信息 。 如图 , 红色的平行四边形就是上面立方体的"底座"信息 , 而绿色是它的高度信息(如果你需要一些更细致的排序 , 比如算上z轴 , 本文暂不讨论)有了这个信息 , 我们就可以确定任意两个对象之间的绘制顺序 。
我们把两个要排序的物体分别命名为A和B , A底座的上边缘称为aTop , 下边缘称为aBottom;B底座的上边缘称为bTop , 下边缘称为bBottom 。
aBottom的y坐标小于bTop的y坐标:

【干货】制作 oblique/cabinet 投影的 2D 游戏时,确认精灵先后顺序的排序方法
文章图片
这时候A显然是在B的后方 , 也就是A先于B渲染 。
aTop的y坐标大于bBottom的y坐标:

【干货】制作 oblique/cabinet 投影的 2D 游戏时,确认精灵先后顺序的排序方法
文章图片
这时候A显然是在B的前方 , 也就是B先于A渲染 。
其它的情况:

【干货】制作 oblique/cabinet 投影的 2D 游戏时,确认精灵先后顺序的排序方法
文章图片
由于我们这里的视角下 , 侧面是一个45度的斜线 , 所以我们可以很轻松地把两个物体下边缘的y轴距离加到aBottom的右端点去进行判断 , 像是这样:
distanceY=bBottom.y-aBottom.y
(我们用left和right表示一个线段的左端点和右端点)
aBottom.left.x>bBottom.right.x+distanceY
如果这个判断是成立的 , 那就是上图所述的情况:A在B的前方 , 也就是B先于A渲染 。
否则就是下图所述的情况:A在B的后方 , 也就是A先于B渲染 。

【干货】制作 oblique/cabinet 投影的 2D 游戏时,确认精灵先后顺序的排序方法
文章图片
对场景内所有物体的排序
好 , 至此我们已经可以为场景内任意的两个对象进行排序了 , 那么 , 我们也可以为场景中所有的对象组织排序 。 很多人的第一反应是 , 直接用冒泡/选择/归并/快排这样的算法来对场景中需要排序的物体进行排序不就好了吗?其实这是不合适的 , 因为场景中的物体遮挡存在拓扑关系 , 如果直接使用线性表的排序方法 , 可能在swap一对物体以确保他们遮挡关系的同时又会直接破坏了另一对物体的遮挡关系 , 因此 , 我们的第一步是对场景中需要排序的物体进行连线 。

【干货】制作 oblique/cabinet 投影的 2D 游戏时,确认精灵先后顺序的排序方法