用移动触摸旋转精灵节点

时间:2017-09-07 05:03:29

标签: ios swift sprite-kit rotation

我是Swift和SpriteKit的新手,我正在学习如何理解游戏中的控制" Fish&跳闸&#34 ;.精灵节点始终位于视图的中心,它会根据移动您的触摸而旋转,无论您在何处触摸和移动(保持)它都会相应地旋转。

这里的难点在于它与Pan Gesture和简单的触摸位置不同,如图1和图2所示。

enter image description here

对于第一张图片,触摸位置由atan2f处理,然后发送到SKAction.rotate并完成,我可以使其工作。

对于第二张照片,我可以通过设置UIPanGestureRecognizer来实现这一点,但它可以正常工作,但只有在手指围绕初始点移动时才能旋转节点(touchesBegan)。

我的问题是第3张照片,与Fish&旅行游戏,你可以触摸屏幕上的任何地方,然后移动(按住)到任何地方,节点在你移动时仍然旋转,你不必在初始点周围移动手指让节点旋转和旋转平稳而准确。

我的代码如下,它不能很好地运行并且有一些抖动,我的问题是如何以更好的方式实现它?如何使旋转平稳?

有没有办法过滤touchesMoved函数中的previousLocation?当我使用这个属性时,我总是遇到抖动,我认为报告太快了。当我使用UIPanGestureRecoginzer并且它非常流畅时我没有任何问题,所以我想我必须对previousLocation做错了。

func mtoRad(x: CGFloat, y: CGFloat) -> CGFloat {

    let Radian3 = atan2f(Float(y), Float(x))

    return CGFloat(Radian3)  
}

func moveplayer(radian: CGFloat){

    let rotateaction = SKAction.rotate(toAngle: radian, duration: 0.1, shortestUnitArc: true)

    thePlayer.run(rotateaction)
}

var touchpoint = CGPoint.zero
var R2 : CGFloat? = 0.0

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

    for t in touches{

        let previousPointOfTouch = t.previousLocation(in: self)

        touchpoint = t.location(in: self)

        if touchpoint.x != previousPointOfTouch.x && touchpoint.y != previousPointOfTouch.y {

            let delta_y = touchpoint.y - previousPointOfTouch.y
            let delta_x = touchpoint.x - previousPointOfTouch.x

            let R1 = mtoRad(x: delta_x, y: delta_y)

            if R2! != R1 { 
                moveplayer(radiant: R1)
            }

            R2 = R1
        }             
    }
}

1 个答案:

答案 0 :(得分:1)

这不是一个答案(但是 - 希望稍后发布一个/编辑它),但是你可以通过改变movePlayer()的定义来使你的代码更加'Swifty':

func moveplayer(radian: CGFloat)

rotatePlayerTo(angle targetAngle: CGFloat) {
   let rotateaction = SKAction.rotate(toAngle: targetAngle, duration: 0.1, shortestUnitArc: true)
   thePlayer.run(rotateaction)
}

然后,打电话给它,而不是:

moveplayer(radiant: R1)

使用

rotatePlayerTo(angle: R1)

更具可读性,因为它描述了你做得更好。

此外,你对新角度的旋转恒定为0.1秒 - 所以如果玩家必须进一步旋转,它将旋转得更快。保持转速恒定(以每秒弧度计)会更好。我们可以这样做:

添加以下属性:

let playerRotationSpeed = CGFloat((2 *Double.pi) / 2.0) //Radian per second; 2 second for full rotation

将您的moveShip更改为:

func rotatePlayerTo(angle targetAngle: CGFloat) {
    let angleToRotateBy = abs(targetAngle - thePlayer.zRotation)
    let rotationTime = TimeInterval(angleToRotateBy / shipRotationSpeed)
    let rotateAction = SKAction.rotate(toAngle: targetAngle, duration: rotationTime , shortestUnitArc: true)
    thePlayer.run(rotateAction)
}

这也可能有助于平滑旋转。