swift – 如何设置圆的物理属性,使其遵循给定的路径

物理体圈的运动对于我想要达到的目标来说太不稳定了.我想限制它,以便它遵循某个特定点(或一系列点)的路径,如下图所示.如何设置物理属性以遍历类似的路径?

how to set physics properties for a circle so it follows given path

因此,基本上您希望使用实时运动将节点移动到特定点.我有一个答案here显示如何做到这一点,但考虑到这个问题收到的票数,我将提供更详细的答案.

我所链接的答案没有提供的是遍历点的路径.所以下面我提供了一个解决方案,展示了如何在下面完成.它只是移动到路径中的每个点,每次节点到达一个点时,我们递增索引以移动到下一个点.我还为行进速度,速率(使运动更平滑或静态)以及节点是否应重复路径添加了一些变量.您可以进一步扩展此解决方案,以更好地满足您的游戏需求.我肯定会考虑将节点子类化并将此行为构建到其中,以便您可以将此运动重用于多个节点.

最后一点,你可能会注意到冲动的计算在我的解决方案和我上面提到的答案之间有所不同.这是因为我避免使用角度计算,因为它们非常昂贵.相反,我正在计算法线,以便计算更有效.

最后一点,我的答案here解释了使用速率因子来平滑运动并为运动失真留出空间.

import SpriteKit

class GameScene: SKScene {
    var node: SKShapeNode! //The node.
    let path: [CGPoint] = [CGPoint(x: 100,y: 100),CGPoint(x: 100,y: 300),CGPoint(x: 300,y: 100)] //The path of points to travel.
    let repeats: Bool = true //Whether to repeat the path.
    var pathIndex = 0 //The index of the current point to travel.
    let poinTradius: CGFloat = 10 //How close the node must be to reach the destination point.
    let travelSpeed: CGFloat = 200 //Speed the node will travel at.
    let rate: CGFloat = 0.5 //Motion smoothing.

    override func didMovetoView(view: SKView) {
        node = SKShapeNode(circleOfRadius: 10)
        node.physicsBody = SKPhysicsBody(circleOfRadius: 10)
        node.physicsBody!.affectedByGravity = false
        self.addChild(node)
    }

    final func didReachPoint() {
        //We reached a point!
        pathIndex++

        if pathIndex >= path.count && repeats {
            pathIndex = 0
        }
    }

    override func update(currentTime: NSTimeInterval) {
        if pathIndex >= 0 && pathIndex < path.count {
            let destination = path[pathIndex]
            let displacement = CGVector(dx: destination.x-node.position.x,dy: destination.y-node.position.y)
            let radius = sqrt(displacement.dx*displacement.dx+displacement.dy*displacement.dy)
            let normal = CGVector(dx: displacement.dx/radius,dy: displacement.dy/radius)
            let impulse = CGVector(dx: normal.dx*travelSpeed,dy: normal.dy*travelSpeed)
            let relativeVeLocity = CGVector(dx:impulse.dx-node.physicsBody!.veLocity.dx,dy:impulse.dy-node.physicsBody!.veLocity.dy);
            node.physicsBody!.veLocity=CGVectorMake(node.physicsBody!.veLocity.dx+relativeVeLocity.dx*rate,node.physicsBody!.veLocity.dy+relativeVeLocity.dy*rate);
            if radius < poinTradius {
                didReachPoint()
            }
        }
    }
}

我很快就这样做了,所以如果有错误我会道歉.我现在没有时间,但我会在后面添加一个显示解决方案的gif.

关于碰撞的说明

为了在碰撞过程中修复不稳定的运动,在2个物体碰撞后将“速率”属性设置为0或优选地设置为非常低的数字,以减小行进速度脉冲,这将为您提供更大的运动失真空间.然后在将来的某个时刻(可能在碰撞发生后的某个时间或者最好在身体再次缓慢移动时)将速率设置回其初始值.如果你真的想要一个很好的效果,你实际上可以随着时间的推移将速率值从0增加到初始值,以给自己一个平稳和渐进的加速.

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...