Swift:使用施加的脉冲来计算节点的轨迹

时间:2018-08-13 00:26:01

标签: swift sprite-kit game-physics physics

我想计算一个脉冲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?我可以除以像素对米的比率吗?

2 个答案:

答案 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)