更新: 我已经解决了这个问题,并且找到了一个比提供答案更简单的方法。我的解决方案是使SPACESHIP的速度等于从手指触摸到的距离。为了加快运动速度,可以将该速度乘以一个常数。在这种情况下,我使用了16。我还摆脱了在touchesEnd事件中将lastTouch设置为nil的问题。这样,即使我松开手指,船仍会停下来。
override func update(currentTime: CFTimeInterval) { /* Called before each frame is rendered */ if let touch = lastTouch { myShip.physicsBody.velocity = CGVector(dx: (lastTouch!.x - myShip.position.x) * 16, dy: 0) } }
===============================
我有一个SPACESHIP节点,其运动仅限于X轴。当用户在屏幕上的某个位置按下并按住时,我希望SPACESHIP能够移动到手指的x坐标,而不希望在松开手指之前不停止向手指移动。如果“空格键”靠近用户的手指并且用户的手指仍被按下,则希望它逐渐减速并停止。我还希望当SPACESHIP改变方向,开始和停止时应用这种平滑运动。
我正在尝试找出最佳方法。
到目前为止,我已经创建了节点并且它可以正确移动,但是存在一个问题:如果我按下屏幕并按住不放,船最终将越过我的手指并继续移动。这是因为仅当我移动手指时才会触发更改船方向的逻辑。因此,基本上,将我的手指移到船上以改变船的方向是可行的,但如果船越过我的静止指头,则不会改变方向
我需要SPACESHIP节点来识别它何时越过我的静止手指,并根据其与我手指的接近程度来更改其方向或停止。
以下是相关代码:
第1部分: 当用户按下时,找出触摸来自何处,并使用速度相应地移动myShip(SPACESHIP)
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { /* Called when a touch begins */ let touch = touches.anyObject() as UITouch let touchLocation = touch.locationInNode(self) if (touchLocation.x < myShip.position.x) { myShip.xVelocity = -200 } else { myShip.xVelocity = 200 } }
第2部分: 当用户移动手指时,触发一个事件,检查该手指是否现在已移至船的另一侧。如果是这样,请更改船的方向。
override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) { let touch = touches.anyObject() as UITouch let touchLocation = touch.locationInNode(self) //distanceToShip value will eventually be used to figure out when to stop the ship let xDist: CGFloat = (touchLocation.x - myShip.position.x) let yDist: CGFloat = (touchLocation.y - myShip.position.y) let distanceToShip: CGFloat = sqrt((xDist * xDist) + (yDist * yDist)) if (myShip.position.x < touchLocation.x) && (shipLeft == false) { shipLeft = true myShip.xVelocity = 200 } if (myShip.position.x > touchLocation.x) && (shipLeft == true) { shipLeft = false myShip.xVelocity = -200 } }
第3部分: 当用户从屏幕上松开手指时,我希望飞船停止移动。
override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) { myShip.xVelocity = 0 }
第4部分 更新事件,更改船的位置
override func update(currentTime: CFTimeInterval) { /* Called before each frame is rendered */ let rate: CGFloat = 0.5; //Controls rate of motion. 1.0 instantaneous, 0.0 none. let relativeVelocity: CGVector = CGVector(dx:myShip.xVelocity - myShip.physicsBody.velocity.dx, dy:0); myShip.physicsBody.velocity = CGVector(dx:myShip.physicsBody.velocity.dx + relativeVelocity.dx*rate, dy:0);
感谢您的阅读,并期待得到答复!
使用以下命令可以为您省去很多麻烦myShip.physicsBody.applyImpluse(vector)。它的工作方式就像您myShip在方向vector点上施加了推力一样。如果您计算的vector是从上次触摸位置到的x距离myShip,则它会加速,减速,改变方向等。与您描述的方式非常接近,因为它只会在正确的方向上进行少量推动每个update。
myShip.physicsBody.applyImpluse(vector)
myShip
vector
update
基本上,您存储了最后一次触摸的位置,然后在update函数中计算了CGVector从myShip到的指向,lastTouch并将其作为对物理身体的冲动。
CGVector
lastTouch
就像是:
var lastTouch: CGPoint? = nil override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { let touch = touches.anyObject() as UITouch let touchLocation = touch.locationInNode(self) lastTouch = touchLocation } override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) { let touch = touches.anyObject() as UITouch let touchLocation = touch.locationInNode(self) lastTouch = touchLocation } // Be sure to clear lastTouch when touches end so that the impulses stop being applies override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) { lastTouch = nil } override func update(currentTime: CFTimeInterval) { // Only add an impulse if there's a lastTouch stored if let touch = lastTouch { let impulseVector = CGVector(touch.x - myShip.position.x, 0) // If myShip starts moving too fast or too slow, you can multiply impulseVector by a constant or clamp its range myShip.physicsBody.applyImpluse(impulseVector) } }
您可能还想使用linearDamping和的angularDamping值myShip.physicsBody。它们将帮助确定myShip加速和减速的速度。
linearDamping
angularDamping
myShip.physicsBody
我最大化了1.0我的应用程序中的值:
1.0
myShip.physicsBody.linearDamping = 1.0 myShip.physicsBody.angularDamping = 1.0
如果myShip不能足够快地停止,您还可以尝试对update函数进行一些中断:
override func update(currentTime: CFTimeInterval) { // Only add an impulse if there's a lastTouch stored if let touch = lastTouch { let impulseVector = CGVector(touch.x - myShip.position.x, 0) // If myShip starts moving too fast or too slow, you can multiply impulseVector by a constant or clamp its range myShip.physicsBody.applyImpluse(impulseVector) } else if !myShip.physicsBody.resting { // Adjust the -0.5 constant accordingly let impulseVector = CGVector(myShip.physicsBody.velocity.dx * -0.5, 0) myShip.physicsBody.applyImpulse(impulseVector) } }