如何通过触摸旋转 SpriteNode?

Posted

技术标签:

【中文标题】如何通过触摸旋转 SpriteNode?【英文标题】:How to rotate SpriteNode with touch? 【发布时间】:2017-03-31 17:43:19 【问题描述】:

如何通过触摸在固定点上旋转 SpriteKit 节点。所以当用户拖动手指时它会转动。我也希望能够获得 rpm。 (这个问题之前被问过,但我想知道如何使用 SpriteKit 来做) Swift 3 游乐场

到目前为止,我已经得到了这个可行的方法,但有时我会收到 var deltaAngle = angle - startingAngle 的错误!错误 - “在展开可选值时意外发现 nil”

class GameScene: SKScene 
var startingAngle:CGFloat?
var startingTime:TimeInterval?


override func didMove(to view: SKView) 
    let wheel = SKSpriteNode(imageNamed: "IMG_6797.PNG" )

    wheel.position = CGPoint(x: 200, y: 200)

    wheel.name = "wheel"
    wheel.setScale(0.5)
    wheel.physicsBody = SKPhysicsBody(circleOfRadius: wheel.size.width/2)
    // Change this property as needed (increase it to slow faster)
    wheel.physicsBody!.angularDamping = 4
    wheel.physicsBody?.pinned = true
    wheel.physicsBody?.affectedByGravity = false
    addChild(wheel)


override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) 
    for touch in touches 
        let location = touch.location(in:self)
        let node = atPoint(location)
        if node.name == "wheel" 
            let dx = location.x - node.position.x
            let dy = location.y - node.position.y
            // Store angle and current time
            startingAngle = atan2(dy, dx)
            startingTime = touch.timestamp
            node.physicsBody?.angularVelocity = 0
        
    


override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) 
    for touch in touches
        let location = touch.location(in:self)
        let node = atPoint(location)
        if node.name == "wheel" 
            let dx = location.x - node.position.x
            let dy = location.y - node.position.y


            let angle = atan2(dy, dx)
            // Calculate angular velocity; handle wrap at pi/-pi
            var deltaAngle = angle - startingAngle!
            if abs(deltaAngle) > CGFloat.pi 
                if (deltaAngle > 0) 
                    deltaAngle = deltaAngle - CGFloat.pi * 2
                
                else 
                    deltaAngle = deltaAngle + CGFloat.pi * 2
                
            
            let dt = CGFloat(touch.timestamp - startingTime!)
            let velocity = deltaAngle / dt

            node.physicsBody?.angularVelocity = velocity

            startingAngle = angle
            startingTime = touch.timestamp
        
    




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

    startingAngle = nil
    startingTime = nil

【问题讨论】:

到目前为止你尝试过什么? ;) 我最初打算使用 UIKit (UiGestureRecogniser),但我在 wwdc 操场上使用的 SpriteKit 太少,需要添加更多。我是 SpriteKit 的新手,所以不知道该怎么做@Whirlwind 您应该使用 touchesBegan 和 touchesMoved 覆盖来获取触摸位置,然后计算节点应旋转到的切线角度。对于初学者,请确保您的节点图形资源朝向右侧,否则您的角度会偏离。如果您仍然需要帮助,请从那里开始并返回一些代码。 我已经设法让它工作,但我得到一个错误(编辑问题)@TheValyreanGroup 【参考方案1】:

那个错误的意思正是它所说的。最有可能的是,“***”在 touchesBegan 中没有被触及,但随后在 touchesMoved 中注册,导致startingAngle 没有被设置为任何值并且为零。

如果用户没有开始触摸***,您可能不希望***旋转,所以我会在 touchMoved 中添加一个保护

...
let angle = atan2(dy, dx)

guard startingAngle != nil else return //Exit the function if starting angle was never set

var deltaAngle = angle - startingAngle!
...

【讨论】:

如果用户轻弹代码,代码会旋转***,如何在用户拖动手指时让它旋转?

以上是关于如何通过触摸旋转 SpriteNode?的主要内容,如果未能解决你的问题,请参考以下文章

触摸 Sprite,使其跳起来然后再次落下(重复多次点击 spritenode。)

如何避免 Touches 取消事件?

Unity - 如何根据触摸旋转对象?

如何在转到角度之前将 SKSpriteNode 旋转 360°

如何在不产生 y 旋转抖动的情况下统一使用触摸输入来钳制游戏对象的 z 旋转

如何通过拖动来旋转 qml 矩形?