ios - 使用移动触摸旋转 Sprite 节点

标签 ios swift sprite-kit rotation

我是 Swift 和 SpriteKit 的新手,正在学习理解“Fish & Trip”游戏中的控件。 sprite 节点始终位于 View 的中心,它会根据您触摸的移动而旋转,无论您在哪里触摸和移动(按住)它都会相应地旋转。

这里的困难在于它不同于我在图 1 和图 2 中注意到的平移手势和简单的触摸位置。

enter image description here

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

对于第二张图片,我可以通过设置一个 UIPanGestureRecognizer 来获得它并且它可以工作,但是您只能在围绕初始点 (touchesBegan) 移动手指时旋转节点。

我的问题是第三张图,和Fish & Trip游戏一样,你可以触摸屏幕上的任何地方,然后移动(按住)到任何地方,节点仍然会随着你的移动而旋转,你不会必须围绕初始点移动手指才能让节点旋转并且旋转平滑准确。

我的代码如下,它运行得不是很好而且有些抖动,我的问题是如何以更好的方式实现它?以及如何使旋转顺畅?

有没有办法过滤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
        }             
    }
}

最佳答案

这不是一个答案(但是 - 希望稍后发布一个/将其编辑成一个),但是您可以通过更改 movePlayer() 的定义使您的代码更“敏捷”来自:

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)
}

这也有助于平滑旋转。

关于ios - 使用移动触摸旋转 Sprite 节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46088188/

相关文章:

ios - swift/ SpriteKit : How to create a water drop effect?

swift - 为什么我的 touchesEnded 函数没有初始化?

ios - 单元测试目标的 FirebaseApp.configure() 崩溃

ios - 当设备旋转改变时创建附加约束

ios - numberOfRowsInSection 计数将所有部分行设置为第一个部分计数

swift - NSMakeRect 跟踪 slider Swift 3

ios - 在循环中更改标签字体大小不会更改文本的大小

ios - 构建应用程序时忽略字体?

ios - UIScrollView 中的 UIScreenEdgePanGestureRecognizer

iOS:MKPinAnnotationView 动画放置不起作用