ジャンプするSKActionを作る

SKActionには「ジャンプする」を表すアクションがなかったので作ってみました。

public extension SKAction {
    class func jump(height: CGFloat, duration seconds: TimeInterval) -> SKAction {
        var initialY: CGFloat = 0.0
        var initialFlag = true

        let customAction = SKAction.customAction(withDuration: seconds) {
            node, elapsedTime in
            if initialFlag == true {
                initialFlag = false
                initialY = node.position.y
            }

            let t = elapsedTime/CGFloat(seconds)

            let y: CGFloat
            if t > 0.9995 {
                y = 0
            } else {
                y = -4 * height * t * (t - 1)
            }
            node.position.y = initialY + y
        }
        return customAction
    }
}

パラメータに「ジャンプの高さ」と「滞空時間」を設定すると、その場でジャンプしてくれます。

let jump = SKAction.jump(height: 100, duration: 1.0) // 100ptの高さで1.0秒ジャンプする
node.run(jump)

理屈は簡単で、滞空時間を0-1で正規化した後、(0,0),(ジャンプの高さ,1),(1,0)の3点を通る2次方程式に当てはめているだけです。 ただしそれだけだと、cocos-2dのジャンプでよくあった「ジャンプを続けるとだんだん位置がずれていく」という、最終位置の誤差が積み重なる問題が出てしまうので、ある程度の時間が立ったら地面におろしてしまうようにしています。