【问题标题】:Swift: Calculate trajectory of node with applied impulseSwift:使用施加的脉冲计算节点的轨迹
【发布时间】:2018-08-13 00:26:01
【问题描述】:

我想计算一个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 更长,因此预测的轨迹会更长。我如何能够将轨迹转换为使用像素或CGFloats?有没有可以除以的像素与米的比例?

【问题讨论】:

    标签: swift sprite-kit game-physics physics


    【解决方案1】:

    (从物理学的角度回答,我不是 swift 或 sprite-kit 方面的专家)

    “单位”的选择(以及一个点代表的物理距离)完全由您自己决定,直到您调用 applyImpulse() 的点为止的数学计算与假设 1 点 = 1 米是一致的。这可能是也可能不是您想要的,但这是一个不错的选择 - 顺便说一句,在您的代码中,唯一(某种)将一个点固定到真实世界仪表的是重力值 9.8,否则您可以只是将它们称为点而不改变实际含义 - 物理引擎并不关心。

    您在代码中放入 array[] 的连续球位置是假设发射的球将在一秒钟内覆盖从 start_of_drag 到 end_of_drag 的距离(因为您只是将距离用作速度值,即, 1m 变为 1m/sec, 2m = 2m/s, 等等)。 (注意,我不太清楚 12 点预测路径在您的情况下如何正确工作,因为要获得一个指向拖动方向的向量,您通常会执行 end_drag - start_drag,而您的代码会执行 start - end

    您可能遇到的问题与applyImpulse 期望值以牛顿*秒为单位(并且速度变化将取决于球的质量:delta-V = 脉冲/质量)这一事实有关,而您调用具有相同“距离成为速度”单位的函数。

    如果球在被拖动之前始终是静止的,并且您希望它以选定的速度立即开始移动,那么简单地将其速度分配给所需的值并让它飞起来可能会更容易,而不是尝试使用applyImpulse,例如:

    (编辑:正如@knight0fdragon 指出的那样,SK 的距离单位是点,但速度是以抽象的“米”= 150pt/秒为单位测量的,所以到目前为止,如果您以点和点/秒为单位进行数学计算,您必须在修改physicsBody 向量之前缩放速度:将其除以150.0)。

    ball.physicsBody?.velocity = CGVector(dx:velocityX, dy:velocityY)
    

    如果球已经有一定的速度,并且您想将其修改一些量(以速度单位而不是 N*m 表示)并且忽略质量,将该速度变化添加到球的当前速度。

    【讨论】:

    • 在 sprite kit 中,150 个点是 1 米,因此 1,0 的速度将在 1 秒内将球移动 150 个点
    • @Leo K,感谢您的回复,但首先,applyImpulse 实际上是速度而不是力。其次,我将这个值除以 150,现在它太小了,看起来 150 太大了。
    • '实际上是速度,而不是力'。我没有说它是一种力量,它是冲动——但这与速度不同。看这里,它说明了如何测量脉冲 - 肯定不是 m/s:developer.apple.com/documentation/spritekit/skphysicsbody/…
    • 如果您直接将速度更改应用于 x.velocity 属性(如我建议的那样),则除以 150,而不是如果您使用 applyImpulse。如果您使用后者,但手头有 速度变化,则必须计算实现该变化所需的脉冲 - 只需让 SK 应用反向数学将其转换回速度当你打电话给applyImpulse时改变。
    • 我将您的像素更改为点,因为它们是 2 个不同的单位。在 sprite kit 中,1 点可能等于“X”像素,具体取决于视网膜和缩放模式。
    【解决方案2】:

    只是为了展示我如何将 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)
    

    【讨论】:

    • 你的球的质量是多少?是100KG吗?
    • 质量无关紧要,我只处理速度,但它是 0.24999912083149 个单位
    • 你不是在处理速度,冲量是一种力,所以质量很重要
    • applyimpulse 和 applyforce 之间的唯一区别是 applyimpulse 立即发生,而 applyforce 发生在物理阶段(applyforce 也有一个错误,单位是点而不是米,不确定这是否已经修复)
    • 另一件事是应用力也是 1/60 秒(假设您的 FPS 为 60),其中应用脉冲立即应用整秒。如果您想了解更多信息,SKPhysics 是 Box2D 的衍生产品,因此您可以查看 Box2D 以了解它们在做什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-15
    • 2013-08-12
    相关资源
    最近更新 更多