我试图在这个问题中创建一个类似于“奖杯轮”的可旋转节点。到目前为止,我具有甩尾功能,可以使用效果很好的UIPanGestureRecognizer在物理物体上添加角度脉冲。我也可以通过触摸停止旋转。
现在,我试图通过拖动或滑动手势来微调方向盘,这样,如果玩家对最终的效果不满意,就可以手动旋转/拖动/旋转它所喜欢的旋转方式。
目前,我将触摸的位置保存在touchesBegan中,并尝试在更新循环中增加节点的zRotation。
旋转不跟随我的手指,而且很生涩。我不确定我的手指运动是否获得足够准确的读数,或者手指的变化位置是否没有准确地转换为弧度。我怀疑先检测触摸然后在更新中处理它不是一个很好的解决方案。
这是我的代码。
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent?) { if let touch = touches.first as? UITouch { var location = touch.locationInView(self.view) location = self.convertPointFromView(location) mostRecentTouchLocation = location let node = nodeAtPoint(location) if node.name == Optional("left") && node.physicsBody?.angularVelocity != 0 { node.physicsBody = SKPhysicsBody(circleOfRadius:150) node.physicsBody?.applyAngularImpulse(0) node.physicsBody?.pinned = true } } } override func update(currentTime: CFTimeInterval) { /* Called before each frame is rendered */ if mostRecentTouchLocation != CGPointZero{ let node = nodeAtPoint(mostRecentTouchLocation) if node.name == Optional("left") { var positionInScene:CGPoint = mostRecentTouchLocation let deltaX:Float = Float(positionInScene.x) - Float(node.position.x) let deltaY:Float = Float(positionInScene.y) - Float(node.position.y) let angle:CGFloat = CGFloat(atan2f(deltaY, deltaX)) let maths:CGFloat = angle - (CGFloat(90) * (CGFloat(M_PI) / 180.0)) node.zRotation += maths mostRecentTouchLocation = CGPointZero } } }
我在更新中将一些数学计算分散在多行中,以使调试更加容易。
如果需要,我可以添加PanGestureRecognizer代码,但现在我将尽量使其简短。
编辑 这是基于GilderMan推荐的最新代码。我认为它的效果更好,但是旋转远非平稳。它以较大的幅度跳跃并且没有很好地跟随手指。这是否意味着我的角度计算有问题?
override func didSimulatePhysics() { if mostRecentTouchLocation != CGPointZero { let node = nodeAtPoint(mostRecentTouchLocation) if node.name == Optional("left") { var positionInScene:CGPoint = mostRecentTouchLocation let deltaX:Float = Float(positionInScene.x) - Float(node.position.x) let deltaY:Float = Float(positionInScene.y) - Float(node.position.y) let angle:CGFloat = CGFloat(atan2f(deltaY, deltaX)) node.zRotation += angle println(angle) mostRecentTouchLocation = CGPointZero } } }
以下代码模拟了根据触摸旋转的奖轮。当用户的手指移动时,轮子会与手指的速度成比例地旋转。当用户在方向盘上滑动时,方向盘将与滑动速度成比例地旋转。您可以更改angularDamping物理物体的属性以减慢或增加砂轮停止的速度。
angularDamping
class GameScene: SKScene { var startingAngle:CGFloat? var startingTime:TimeInterval? override func didMove(to view: SKView) { let wheel = SKSpriteNode(imageNamed: "Spaceship") 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 = 0.25 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 // Update angle and time startingAngle = angle startingTime = touch.timestamp } } } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { startingAngle = nil startingTime = nil } }