更新:我已经解决了问题,并找到了更简单的方法,然后提供答案。我的解决方案是使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轴。当用户在屏幕上某处按下并且HOLDS时,我希望SPACESHIP能够移动到手指的x坐标,并且在手指释放之前不会停止向手指移动。如果SPACESHIP靠近用户手指并且仍然按下用户手指,我希望它逐渐减速并停止。我还希望在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);
感谢阅读,期待回复!
答案 0 :(得分:3)
使用:myShip.physicsBody.applyImpluse(vector)
可以省去很多麻烦。它的工作原理就像你向myShip
方向推动vector
一样。如果您将vector
计算为距离上次触摸位置到myShip
的x距离,那么它会加速,减速,改变方向等,非常接近您描述的方式,因为它会在每个update
上向正确的方向推动它。
基本上,您存储了最后一个触摸位置,然后在update
函数中计算从CGVector
指向myShip
的{{1}}并将其作为您的推动应用物理机构。
类似的东西:
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
的最大值:
1.0
如果myShip.physicsBody.linearDamping = 1.0
myShip.physicsBody.angularDamping = 1.0
没有足够快地停止,您还可以尝试在myShip
函数中应用一些中断:
update
答案 1 :(得分:2)
对于2017年,这里可以轻松地执行正确答案中解释的内容。
没有必要存储以前的位置,它是给你的 ......
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let t: UITouch = touches.first! as UITouch
let l = t.location(in: parent!)
let prev = t.previousLocation(in: parent!)
let delta = (l - prev).vector
physicsBody!.applyImpulse(delta)
}
就是这样。
两个音符。(A)你应该正确地将delta距离除以deltaTime以获得正确的脉冲。如果你是一个业余爱好者真的只是乘以“约100”,你会没事的。 (B)请注意,当然你需要一个扩展或功能来将CGPoint转换为CGVector,没有它就不可能做任何事情。
答案 2 :(得分:-1)
在thuchesBegan
和touchesMoved
存储触摸位置作为&#34;目标&#34;。在update
然后检查您的船的位置,如果船已经到达/超过了目标,则将xVelocity
重置为0.
由于您只对x坐标感兴趣,因此您也可以只存储touchLocation.x
。你也可以扭转速度,但我觉得这看起来很奇怪。请注意,如果用户再次移动手指,您的船只将再次开始移动,因为touchMoved
将再次触发。
在旁注上,touchesMoved
内您还设置了shipLeft
属性,但未在touchesBegan
中设置。如果在其他地方使用此属性,则应同步其使用。