Ios 使用Swift+将节点移动到手指上;斯皮特基特
更新:我已经解决了这个问题,并找到了一种比答案更简单的方法。我的解决办法是使宇宙飞船的速度等于我用手指触摸的距离。为了更快的移动,你可以将这个速度乘以一个常数。在本例中,我使用了16。在TouchSend事件中,我还将lastTouch设置为零。这样,即使我松开手指,船也会停下来Ios 使用Swift+将节点移动到手指上;斯皮特基特,ios,swift,sprite-kit,Ios,Swift,Sprite Kit,更新:我已经解决了这个问题,并找到了一种比答案更简单的方法。我的解决办法是使宇宙飞船的速度等于我用手指触摸的距离。为了更快的移动,你可以将这个速度乘以一个常数。在本例中,我使用了16。在TouchSend事件中,我还将lastTouch设置为零。这样,即使我松开手指,船也会停下来 override func update(currentTime: CFTimeInterval) { /* Called before each frame is rendered */ if let tou
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)
}
}
===============================
我有一个太空船节点,它的运动限制在X轴上。当用户按住屏幕上的某个位置时,我希望飞船能够移动到手指的x坐标,并且在手指松开之前不会停止向手指移动。如果飞船靠近用户的手指,但用户的手指仍被按下,我希望它逐渐减速并停止。我还希望在宇宙飞船改变方向、启动和停止时应用这种平滑的运动
我正试图找出最好的方法来做到这一点
到目前为止,我已经创建了节点,它可以正确移动,但有一个问题:如果我按下屏幕并按住,飞船最终会越过我的手指并继续移动。这是因为只有当我移动手指时,才会触发改变船舶方向的逻辑。因此,从本质上说,将我的手指移到船上以改变船的方向是可行的,但如果船越过我的静止手指,它不会改变方向
我需要太空船节点识别它何时越过我静止的手指,并根据它离我手指的距离改变方向或停止
以下是相关代码:
第1部分:当用户按下时,找出触摸的来源,并使用速度相应地移动我的飞船(太空船)
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
}
}
第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);
感谢阅读,期待回复 在您的
thuchesBegan
和touchsmoved
中,将触摸位置存储为“目标”。在更新
中,然后检查您的船舶的位置,如果船舶已达到/通过目标,则将xVelocity
重置为0
因为您只对x坐标感兴趣,所以也可以只存储touchLocation.x
。你也可以反转速度,但我认为这看起来很奇怪。请注意,如果用户再次移动手指,您的飞船将再次开始移动,因为touchMoved
将再次触发
另一方面,在
touchsmoved
中,您还设置了shipleet
属性,但这不是在touchsbegind
中设置的。如果此属性在其他地方使用,您应该同步它的使用。通过使用:myShip.physicsBody.applyImpluse(vector)
,您可以省去很多麻烦。它的工作原理是,好像你给了myShip
一个方向vector
点的推力。如果你计算向量
作为你最后一次触摸位置到myShip
的x距离,那么它会加速、减速、改变方向等。非常接近你描述的方式,因为它会在每次更新
时向正确的方向轻轻推动
基本上,您存储最后一次触摸的位置,然后在update
函数中,计算CGVector
从myShip
指向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)
}
}
您可能还需要在myShip.physicsBody
上使用linearDamping
和angularsdamping
值。它们将帮助确定myShip的加速和减速速度
我在我的应用程序中最大化了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)
}
}
对于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)
}
override func touchesMoved(touch:Set,带有事件:UIEvent?){
让t:UITouch=touch.first!作为UITouch
设l=t.location(in:parent!)
让prev=t.previousLocation(在:父对象中!)
设delta=(l-prev).vector
physicsBody!.applyImpulse(增量)
}
就这样
两个音符。(A) 正确地说,你应该用delta距离除以deltaTime得到正确的脉冲。如果你是一个业余爱好者,只要乘以“大约100”,你就没事了。(B) 请注意,当然,您需要一个扩展或函数来将CGPoint转换为CGVector,没有它就不可能做任何事情。哇,首先,非常感谢您花时间给出如此详细的回答!你太棒了!在触摸结束时将lastTouch更改为nil是一种天才之举——这也是这种新语言力量的一个很好的例子。我被什么东西卡住了。出于某种原因,我在更新函数中遇到一个错误:“让pulseVector:CGVector=CGVector(lastTouch.x-myShip.position.x,0)”它说CGPoint没有名为x的成员。发生了什么事?不客气!设置
pulsevector
时遇到的问题是我的输入错误,对此表示抱歉。它应该是touch
,而不是lastTouch
。我编辑了我的答案并修正了。迈克,非常感谢!我用触摸代替了上次触摸,程序运行了。这给了我一个很好的起点来进一步调整它。最后的几个问题/想法。在第三个示例部分中,您是指“myShip.physicsBody.applyImpulse(pulseVector)”而不是pulseDirection吗?此外,我对“if let touch=lastTouch”sta感到困惑
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)
}
}
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)
}