Swift:设置距离的速度

7
我正在尝试在Swift上制作一个移动平台,为了使玩家与平台一起移动,我需要将self.moveByX()更改为physicsBody?.velocity(并给平台和玩家都加入一些摩擦力)。

因此,我创建了以下函数:

self.runAction(
    SKAction.repeatActionForever(
        SKAction.sequence([
            SKAction.runBlock({
                print(self.position.x)
                self.physicsBody?.velocity = CGVectorMake(20, 0.0)
            }),
            SKAction.waitForDuration(3),
            SKAction.runBlock({
                print(self.position.x)
                self.physicsBody?.velocity = CGVectorMake(-20, 0.0)
            }),
            SKAction.waitForDuration(3)
        ])
    )
)

问题在于我原以为两个位置之间的距离是确切的60(20 * 3秒),但我收到了平台x的位置日志如下:
596.042907714844
544.228393554688
596.048950195312
544.234008789062
596.054565429688
544.116333007812
595.936584472656
544.121887207031
595.942199707031
544.127685546875
595.824584960938
544.009704589844

因此,这些职位之间的差距大约在51~52之间。

如何通过改变速度使平台以特定和精确的距离移动?

编辑:我不知道这是否相关,但我已经设置了平台的物理体如下:

self.physicsBody = SKPhysicsBody(rectangleOfSize: self.size)
self.physicsBody?.categoryBitMask = PhysicsCategory.Ground
self.physicsBody?.contactTestBitMask = PhysicsCategory.Player
self.physicsBody?.collisionBitMask = PhysicsCategory.Player
self.physicsBody?.allowsRotation = false
self.physicsBody?.affectedByGravity = false
self.physicsBody?.dynamic = true
self.physicsBody?.friction = 1.0
self.physicsBody?.restitution = 0.0
self.physicsBody?.mass = 99999999999

我已经有一段时间没有使用Sprite Kit了。但是我猜你一遍又一遍地重复速度。在你的“SKAction.runBlock”中,尝试在应用“self.physicsBody?.velocity”之前将速度重置为零。再次强调,这只是一个猜测,我不再使用SpriteKit了。但是两个物体的摩擦/速度损失可能不同。重置速度可能会解决问题。祝你好运。 - the_pantless_coder
是的,我也尝试过了,问题并没有改变。 - Sergio Toledo Piza
纯粹为了测试,你尝试过让两个对象大小/质量相同吗?当你这样做时,问题是否消失了? - the_pantless_coder
我已经尝试过了,它也没有改变任何东西。 - Sergio Toledo Piza
也许摩擦力会影响结果?尝试将摩擦力设置为0或者self.physicsBody?.dynamic = false来进行测试。 - Simone Pistecchia
你能把你的项目放到GitHub上吗?如果可以,发个链接给我,我会看一下……我很好奇出了什么问题。这似乎是消磨空闲时间的好方法 :) - the_pantless_coder
1个回答

2
我之前没有使用过Sprite Kit,但我认为你的问题在于SKPhysicsBody的linearDamping属性默认设置为0.1,通过快速计算(20*3-20*3*0.1 = 54),如果每帧速度被阻尼,这听起来大约正确。
下面是该属性的文档:

https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKPhysicsBody_Ref/index.html#//apple_ref/occ/instp/SKPhysicsBody/linearDamping

编辑:我认为我至少应该检查一下我的答案,所以我写了一个快速(粗略)的程序:
var dampingOccurancesPerSecond = 60.0 //Corresponds to frame rate
var numberOfSeconds = 3.0
var time = 0.0

@IBAction func test(sender: UIButton) {
    let result = checkDistanceForVelocity(20, damping: 0.1, distanceTraveled: 0.0)
    print(result)
}

 func checkDistanceForVelocity(velocity: Double, damping: Double, distanceTraveled: Double) -> Double {

    if time < numberOfSeconds {

        time += 1/dampingOccurancesPerSecond

        let newVelocity = velocity - (velocity * damping/dampingOccurancesPerSecond)

        let newDistance = (distanceTraveled + velocity/dampingOccurancesPerSecond)

        return checkDistanceForVelocity(newVelocity, damping: damping, distanceTraveled: newDistance)

    }

    return distanceTraveled

}

你旅行距离的微小变化也可能是由于帧速率的微小变化引起的。当阻尼发生次数每秒从60 -> 50时,总旅行距离会从52.1203109538336 -> 51.8808576268828发生改变。
希望这能帮到你!

我能否从平台的物理体中移除线性阻尼? - Sergio Toledo Piza
是的,绝对可以。只需将物理体的linearDamping属性更改为0.0即可: - Olivier Wilkinson
self.physicsBody?.linearDamping = 0.0 - Olivier Wilkinson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接