3.6 跳跃

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/asd77882566/article/details/78797321

跳跃是角色移动的一个大问题。失败的跳跃结果会导致很严重的影响。

3.6.1 跳跃点(Jump Points)

跳跃点是一种最容易支持的跳跃设计,它由关卡设计者在关卡中标记,包含坐标和跳跃需要的最小速度信息。效果如下图所示:

这里写图片描述

这种情况不考虑角色需要努力使用一个刚好的方向。跳跃的角色应该能够被允许以任何速度(超过最低速度)并且在大致正确方向上跳跃(the character should be allowed to have any velocity with a sufficiently large component in the correct direction)。如下图示:

这里写图片描述

然而在下边的情况下,以相同的策略会导致灾难:

这里写图片描述

为了实现跳跃,角色可以使用一个速度匹配的转向行为来执行,在他跳跃前的一段时间,移动的目标是跳跃点,匹配的速度是跳跃点提供的速度。当角色到达跳跃点时,跳跃行为被执行,角色变成飞行。

就像之前提到的一些灾难情况,跳跃点无法提供当前跳跃的足够信息,当着陆地点很狭窄时,就会出现问题,这就需要关卡设计者来避免出现这种情况。

3.6.2 着陆点(Landing Pads)

着陆点是跳跃点的目标区域,在角色起跳之前,增加一个额外的步骤,通过类似轨道预测的算法,计算出角色从起跳点到着陆点需要的速度。

轨道计算

扫描二维码关注公众号,回复: 3160568 查看本文章

起跳的轨道计算和之前提到过的火炮方案有些轻微差别。在当前的情况下,我们知道起始点S,结束点E,重力g和起跳时的y速度Vy。我们不知道的事整个过程的时间t或者起跳的x和z速度。我们可以得到三个公式:

Ex=Sx+vxt

Ey=Sx+vyt+12gyt2

Ez=Sz+vzt

可以计算出对应的结果:

t=vy±2g(EySy)+vy2g

vx=ExSxt

vz=EzSzt

对于跳跃时间t,有两个可能的结果,我们希望以更快的时间完成,使用更小的值,如果我们跳跃速度无法达到时,就使用更大的那个时间t。

为了实现跳跃,需要实现一个从起跳点到着陆点的转向行为。这个行为必须独立于其他的转向行为并且完全控制角色,如果结合其他行为,通常会变成一个失败的跳跃。

实现代码如下:

class Jump(VelocityMatch):
    jumpPoint
    canAchieve = False
    maxSpeed
    maxYVelocity

    def getSteering():
        if not target:
            target = calculateTarget()

        if not canAchieve:
            return new SteeringOutput()

        # character继承于VelocityMatch基类
        if character.position.near(target.position) and
            character.velocity.near(target.velocity):
            # 进行跳跃
            scheduleJumpAction()
            return new SteeringOutput()

        return VelocityMatch.getSteering()

    def calculateTarget():
        target = new Kinematic()
        target.position = jumpPoint.jumpLocation

        # 计算第一个跳跃时间
        sqrtTerm = sqrt(2*gravity.y*jumpPoint.deltaPosition.y + maxYVelocity*maxYVelocity)
        time = (maxYVelocity - sqrtTerm) / gravity.y

        if not checkJumpTime(time):
            time = (maxYVelocity + sqrtTerm) / gravity.y
            checkJumpTime(time)

    def checkJumpTime(time):
        vx = jumpPoint.deltePosition.x / time
        vz = jumpPoint.deltaPosition.z / time
        speedSq = vx*vx + vy*vy

        canAchieve = false
        if speedSq < maxSpeed *maxSpeed:
            target.velocity.x = vx
            target.velocity.z = vz
            canAchieve = true

        return canAchieve

数据结构和接口:

struct JumpPoint:
    jumpLocation
    landingLocation
    deltaPosition

scheduleJumpAction函数强制对象在空中 ,他可以排定一个行为到一个顺序行为队列(第五章详细介绍),或者他只是把需要的速度指定到角色上。

相对于将起跳点作为一个对象,很多开发者将它包含在他们的寻路框架中。第四章中讨论寻路。作为一个寻路系统,我们创建一个游戏的位置网络,这些连接存储了各个位置的连接信息(通常是连接点的距离)。我们可以将跳跃信息加入这些连接中。

3.6.3 孔填充(Hole Fillers)

一些开发者允许角色自己选择他们的起跳点。关卡设计者用一个不可见的对象填充孔洞,作为一个可跳跃的缺口。

角色正常的移动,但是有一个特殊的碰撞避免的变量(我们称之为跳跃探测器)。这个行为对待可跳跃缺口的碰撞,不会躲避,而是全速朝向缺口在抵达碰撞点时执行跳跃行为。

这种方式有很强的灵活性,角色不再限制在一组的跳跃点。然而由于并没有着陆区和目标速度的概念,仍然可能导致一些跳跃失败的情况。在使用这种方式的时候,需要尽量保证关卡设计不会导致这样的情况发生,空洞有足够的跳跃缺口和着陆空间。

猜你喜欢

转载自blog.csdn.net/asd77882566/article/details/78797321
3.6