当前市面上有许多2D类型的格斗游戏,比如经典的KOF,侍魂,DNF,还有现今的摸头村手游等等,2D游戏众所周知只有两个轴——X轴和Y轴,需要完成攻击判定也仅仅只能通过构建一个2D的碰撞器,通过碰撞器检测碰撞来完成攻击判定,比如经典的KOF的攻击判定可以简单的用以下图表示:
我们可以为草薙京和八神庵分别构建两个人物碰撞器,当两个碰撞器相交则认为攻击判定成立,执行后续的被击动作播放、攻击伤害判定等一系列操作。
但当我们用同样的方法放到DNF上,则发现会有明显的不同,我们为以下情形构建碰撞器:
可以看到我释放了一段非常炫酷的剑技,而碰撞器也很明显的相交,但是沙袋却没有任何反应,简单的来说——我空大了!
从图中来看,我与沙袋可以构建一个3维坐标系,可以发现虽然我与沙袋的X轴和Z轴都相交,但在Y轴上相差的太远,而我的技能的Y轴范围并不够大,导致我的技能放空,常玩游戏的玩家甚至可以一眼看出来我的角色需要往下走一些才能命中这个沙袋。
那么问题来了:DNF难道是个3D游戏吗,因为他可以做到Y轴上的判定,而这显然是KOF所不具备的。但很遗憾,DNF是一个纯纯正正的2D游戏,那他是如何做到仿佛3D游戏一样完成使用一个3维碰撞器的效果?
在解决这个问题之前,首先来看看上面的碰撞器构建有什么问题?如果仅仅通过为角色构建一个碰撞器来进行攻击判定的话,那么以下的情况该如何判定:
可以看到这我与沙袋的碰撞器很明显的相交,但是却没有任何一方发起攻击,因此两者不应该存在攻击的碰撞检测,再比如下图案例:
在我释放如此炫酷的技能的时候,我的攻击范围一定是非常大的,那此时我的受击范围又该如何,应该与攻击范围相同?如果这样做那游戏的打击感将会非常奇怪,因此我们应当将碰撞器分割为两种:攻击碰撞器和受击碰撞器。
我们将一个碰撞器拆分为两个碰撞器——红色的攻击碰撞器和绿色的受击碰撞器,当一个角色的攻击碰撞器与另一个角色的受击碰撞器相交,那么便判定为攻击命中,攻击碰撞器与攻击碰撞器相交,或攻击碰撞器与受击碰撞器相交,则不会有任何反应——或者你可以为你的游戏做一些其他的设置,但这些并不在本文的讨论范围内。
话回上文,要如何做到Y轴上的攻击判定,首先了解一下3D游戏下三维碰撞器是如何检测碰撞的——通过两个碰撞器的坐标值(x,y,z)的对比,而2D游戏下坐标值没有z值,只有x和y值,就需要其他的办法来模拟z值。既然我们可以将一个碰撞器分成攻击碰撞器和受击碰撞器,那么为什么不能将碰撞器再度分割,形成攻击碰撞器和地面碰撞器。
我们再度添加一个紫色的地面碰撞器,并用红色的攻击碰撞器代表攻击的X轴范围,用地面碰撞器代表攻击可以命中的Y轴范围,所以攻击命中的条件变成:攻击碰撞器与受击碰撞器相交,且地面碰撞器与地面碰撞器相交。
当然地面碰撞器同样需要分为攻击地面碰撞器——代表本次攻击的Y轴范围,和受击地面碰撞器——代表人物的Y轴碰撞范围,需要这么分的原因一是有些技能的Y轴范围会比角色的Y轴碰撞范围要大,另一个原因是一些游戏存在远程技能,当释放完这些技能后人物可以随意移动,所以攻击碰撞器需要与受击碰撞器独立区分。另外地面碰撞器代表的是Y轴范围,它与X轴无关,因此地面碰撞器的X轴应该尽可能大。
上图是一个脱手远程技能的碰撞器演示,提现了将地面碰撞器分成攻击地面碰撞器和受击地面碰撞器的必要性。
当你的游戏做到以上步骤,实际上就已经结束了——如果你的游戏没有“跳跃”这个概念的话。如果你想要做一个BOSS,该BOSS有一个超级无敌的全屏技能,并且伤害非常高,你想要你的角色只能跳到空中才能躲避这个技能,那么该怎么制作这个技能?只靠上面的碰撞器可以完成这个功能吗?
很遗憾,仅靠这些碰撞器还不足以完成这个功能,首先需要明确一点:跳跃时仅涉及Z轴,并不涉及Y轴,因此在角色跳跃时,角色的地面受击碰撞器不应该移动,那么在角色面对全屏攻击且角色是跳跃状态时,碰撞器的展示应该是这样:
我们可以看到,红色的攻击碰撞器器与绿色的受击碰撞器相交,而紫色的地面攻击碰撞器与橙色的角色受击碰撞器相交,我们应当可以认定本次攻击应该会击中角色,但是从图中直观感受来看,本次攻击只是地面的熔岩攻击,应当没有足够的高度去攻击到在空中的角色的。因此要满足“空中躲避”的功能,需要再增加一个碰撞器——空中碰撞器,同时将空中碰撞器也分为攻击空中碰撞器和受击空中碰撞器,分别表示攻击的Z轴高度和角色的Z轴碰撞范围。
添加了攻击空中碰撞器(蓝色)和受击空中碰撞器(白色)后,我们的全部碰撞器也构建完成了,需要注意的是空中碰撞器仅代表Z轴范围,因此当角色在X轴和Y轴上移动时,攻击碰撞器不应该改变,只有在角色跳跃时才会跟随角色同步改变,且空中碰撞器的X轴范围应当足够大,Y轴代表碰撞高度。
总之,需要明白的就是:2D模拟3D碰撞,需要使用3个碰撞器来模拟三维的一个碰撞器,三个碰撞器分别模拟X轴碰撞、Y轴碰撞、Z轴碰撞,来弥补没有Z坐标的缺陷,虽然过程相对繁琐且笨拙,但总算可以完成与三维下同样的功能。
PS:在说到X,Y,Z轴时,使用的是游戏玩家普遍理解的X,Y,Z轴,即横向X,纵向Y,高度Z,而当说到坐标点时,使用的是游戏开发中的普遍理解:横向X,纵向Z,高度Y。
另外,我用Unity制作了关于碰撞器的简单的Demo,有兴趣的可以下载试用,虽然画面非常简陋,但是也尽量模拟了碰撞器的原理,可以更加深入的理解原理。
链接:https://pan.baidu.com/s/1xKBY6DRz--97zJ9flMKbWA
提取码:abtq
操作方法:wasd主角移动,j主角攻击,k主角跳跃,上下左右方向键敌人移动,L敌人跳跃。
另外源码本人也分享到git上,有兴趣的朋友可以下载指教。
git地址:https://github.com/tyc123cc/2D-3DMode