我想计算一个脉冲SKSpriteNode
的轨迹。我有12个球,我想将它们放置在球发射后的位置。我正在使用公式(t)=₀+t(₀+½Δt)+½t²
我对节点施加的脉冲基于用户在屏幕上拖动的长度。
这是我尝试过的:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
startPositionDrag = location
}
}
在touchesMoved
中,我更新了轨迹节点以显示该节点在该位置发射时将去向何方。
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
movedLocation = touch.location(in: self)
calculateTrajectoryy(velocityY: (startPositionDrag.y - movedLocation.y), velocityX: (startPositionDrag.x - movedLocation.x))
}
这是我使用等式的地方。我有12个球的阵列。我将i
用作时间是因为我想将每个球放在i
秒之后节点将位于的位置。
func calculateTrajectoryy(velocityY: CGFloat, velocityX: CGFloat){
for i in 0...12{
let time = CGFloat(i)
let accelerationX = CGFloat(0)
let accelerationY = CGFloat(-9.8)
var x = CGFloat()
var y = CGFloat()
// (t)=₀+t(₀+½Δt)+½t²
x = ball.position.x + time * (velocityX + 0.5 * time * accelerationX) + 0.5 * time * time * accelerationX
y = ball.position.y + time * (velocityY + 0.5 * time * accelerationY) + 0.5 * time * time * accelerationY
arrray[i].position = CGPoint(x: x, y: y)
}
}
最后,在touchesEnded
中,当用户放开拖动时,该节点将被施加一个脉冲,它应精确地沿着所创建的球的路径运动。
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
ball.physicsBody?.applyImpulse(CGVector(dx:(startPositionDrag.x - endPositionDrag.x), dy:(startPositionDrag.y - endPositionDrag.y))
}
}
}
球不跟随球创建的弧线。球射出一点点,而球的弧线又大又长。我认为这可能与单位换算有关。该方程式将速度值以米/秒为单位,而向后拖动的位置为CGFloat
。仪表比CGFloat
更长,因此预测的轨迹也更长。如何转换轨迹以使用像素或CGFloat
s?我可以除以像素对米的比率吗?
答案 0 :(得分:1)
(从物理学的角度出发,我不是swift或sprite-kit的专家)
“单位”(以及一个点代表的物理距离)的选择完全由您决定,在假设1点= 1米的情况下,您算到applyImpulse()
为止的数学式是一致的。这可能是您想要的,也可能不是您想要的,但这是一个不错的选择-顺便说一句,在代码中(排序)将点固定到现实世界中的仪表的唯一值是9.8的引力值,否则您可以只是称它们为点而没有真正的意义-物理引擎并不在乎。
在代码中放入array []的连续球位置是基于以下假设:发射的球将在一秒内覆盖从start_of_drag到end_of_drag的距离(因为您只是将距离用作速度值,即,则1m变为1m / sec,2m = 2m / s,依此类推)。
(请注意,我不太了解12点预测路径在您的情况下如何正常工作,因为要获得指向拖动方向的向量,通常您会end_drag - start_drag
,而代码会{{ 1}})
您可能要解决的问题是,start - end
期望以牛顿*秒为单位的值(速度变化将取决于球的质量:ΔV=脉冲/质量),而您可以使用相同的“要成为速度的距离”单位来调用该函数。
如果在拖动之前球始终是静止的,并且您希望它立即以选定的速度开始向某处移动,那么将其速度简单地分配给所需的值并让其飞行可能会比尝试使用applyImpulse
,例如:
(edit:正如@ knight0fdragon所指出的那样,SK的距离单位是点,但是速度是以抽象的“米” = 150pt / sec的单位来度量的,所以到目前为止,如果您以点和点/秒为单位进行数学计算, ,则必须先修改速度,然后再修改PhysicsBody向量:将其除以150.0)。
applyImpulse
如果球已经具有某个速度,并且您想要对其进行一些修改(以速度单位表示,而不是N * m),并且不考虑质量,则将该速度更改添加到球的当前速度中。
答案 1 :(得分:0)
仅显示我如何将Leo K的答案应用于代码。
我以某种方式使用像素与英寸之比的150并将其设置为1.5,将其除以1.5作为轨迹,并将其乘以作为冲量。它几乎可以准确预测节点的路径。
calculateTrajectoryy(velocityY: (startPositionDrag.y - movedLocation.y) / 1.5, velocityX: (startPositionDrag.x - movedLocation.x) / 1.5)
ball.physicsBody?.applyImpulse(CGVector(dx:(startPositionDrag.x - endPositionDrag.x) * 1.5, dy:(startPositionDrag.y - endPositionDrag.y) * 1.5)