通过操纵杆实现一致且平稳的运动

时间:2017-02-01 18:10:05

标签: ios swift sprite-kit skspritenode

所以这是我在touchesMoved函数和所有工作中放置的代码。我也有办法停止其他未在此处发布的功能中的每个动画和动作。

我遇到的问题,在我完成编码之前对我来说相当明显的是,机芯会断断续续/抖动,这不是我想要的平滑度。我还想问一下如何限制精灵移动的速度,你可以看到它按变量“v”移动,这取决于你从操纵杆移动的距离。

我的操纵杆的工作方式是初始触摸是“基础”,你移动的位置也是新方向。

TLDR:如何限制当前速度基于变量“v”的移动速度并使移动更加平滑?

    for touch in touches {
        let location = touch.location(in: self)

        let v = CGVector(dx: location.x - joystickMove.x, dy: location.y - joystickMove.y)
        let angle = atan2(v.dy, v.dx)
        deg = angle * CGFloat(180/M_PI)
        readyToMove = true


        switch(deg){

        case -44...45:
            player.walkRight()
            let action = SKAction.moveBy(x: v.dx, y: v.dy, duration: 0.5)
            let repeatAction = SKAction.repeatForever(action)
            player.run(repeatAction, withKey: "move")
            break;
        case 46...135:
            player.walkUp()
            let action = SKAction.moveBy(x: v.dx, y: v.dy, duration: 0.5)
            let repeatAction = SKAction.repeatForever(action)
            player.run(repeatAction, withKey: "move")
            break;
        case 136...180, (-180)...(-135):
            player.walkLeft()
            let action = SKAction.moveBy(x: v.dx, y: v.dy, duration: 0.5)
            let repeatAction = SKAction.repeatForever(action)
            player.run(repeatAction, withKey: "move")
            break;
        case (-134)...(-45):
          player.walkDown()
            let action = SKAction.moveBy(x: v.dx, y: v.dy, duration: 0.5)
            let repeatAction = SKAction.repeatForever(action)
            player.run(repeatAction, withKey: "move")
            break;
        default:

            break;
        }
}

2 个答案:

答案 0 :(得分:1)

抖动是由SKActions每次运行0.5秒引起的。同时可以发生多个其他触摸事件,这可以触发多个其他动作。 您还将每次新动作添加到精灵中,并永久重复。

我会将动画移动到更新方法:

var lastUpdateTime = TimeInterval()
var yourSpriteSpeed: CGFloat = 100.0
override func update(_ currentTime: TimeInterval) {

    let dt = CGFloat(currentTime - lastUpdateTime)
    lastUpdateTime = currentTime

    player.position = CGPoint(x: player.position.x + dx * yourSpriteSpeed * dt, y: player.position.x + dy * yourSpriteSpeed * dt)


}

答案 1 :(得分:0)

要将矢量v限制为特定幅度,您需要检查其幅度是否超过阈值,然后将其标准化。

伪代码:

func mag(v) -> Double {
    return sqrt(v.x * v.x + v.y * v.y)
}

func mult(v, amount) -> Vector {
    return Vector(v.x * amount, v.y * amount)
}

func div(v, amount) -> Vector {
    return Vector(v.x / amount, v.y / amount)
}

func unit(v) -> Vector {
    return  v.div(mag(v))
}

现在你做了:

// ... compute v as before

if mag(v) > MAX_SPEED {
    v = unit(v).mult(MAX_SPEED)
}

// use v.x, v.y as before

虽然这种方法会限制你的操纵杆速度,但我怀疑它会彻底摆脱你的抖动问题(它只是将它缩回到MAX_SPEED的数量)。

PS:要获得完全平滑的运动,您需要将位置和速度保持为单独的变量,并且具有由操纵杆控制的目标速度的概念。在每一帧,您可以根据当前速度和 lerp 当前速度更新位置到目标速度。

速度的突然变化是引起紧张的原因; lerping是一种平滑它的方法。