如何使SpriteKit跳转到特定的高度?

我正在尝试使用applyImpulse来使精灵跳转到特定的高度。 在下面的示例代码中,dynamic黑色圆圈跳转到与静态红色圆圈相同的高度,但只适用于kludge。

如果我的物理是正确的,发射到高度Y的弹丸所需的初始垂直动量是由质量* sqrt(2 * gravity * Y)给出的。 然而这个公式导致黑圈移动很less。

通过反复试验,我发现如下代码所示,通过将脉冲向量的垂直分量乘以12.3,我可以使红圈几乎准确地跳跃。

这似乎是完全武断的,正在让我发疯。 我显然做错了什么。 什么是正确的方法来做到这一点?

这是我认为是相关的代码位:

let dy = mass * sqrt( 2 * -self.physicsWorld.gravity.dy * (fixedCircle.position.y-jumpingCircle.position.y)) * 12.3 jumpingCircle.physicsBody?.applyImpulse(CGVectorMake(0, CGFloat(dy))) 

这是GameScene.swift类的整体,如果你想复制和粘贴…

 import SpriteKit class GameScene: SKScene { var jumpingCircle = SKShapeNode() var fixedCircle = SKShapeNode() override func didMoveToView(view: SKView) { self.scaleMode = .AspectFit // Create an exterior physical boundary self.physicsBody = SKPhysicsBody(edgeLoopFromRect:self.frame) self.physicsWorld.gravity = CGVectorMake(0, -5); // Create the jumping circle jumpingCircle = SKShapeNode(circleOfRadius: 50) jumpingCircle.position = CGPoint(x: 100,y: 0) jumpingCircle.strokeColor = .blackColor() jumpingCircle.physicsBody = SKPhysicsBody(circleOfRadius: 50) jumpingCircle.physicsBody?.linearDamping = 0.0 self.addChild(jumpingCircle) // Create the fixed circle fixedCircle = SKShapeNode(circleOfRadius: 50) fixedCircle.position = CGPoint(x: 100,y: 384) fixedCircle.strokeColor = .redColor() self.addChild(fixedCircle) } override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) { // to reach certain height, initial y velocity should by sqrt(2 * gravity * Y) // momentum required to reach this velocity is mass * velocity // therefore, vertical impulse should be given by mass * sqrt(2 * gravity * Y) if let mass = jumpingCircle.physicsBody?.mass{ // calculate vertical impulse // this formula "should work" but does not // let dy = mass * sqrt(2 * -self.physicsWorld.gravity.dy * (fixedCircle.position.y-jumpingCircle.position.y)) // this formula "works", but has the arbitrary multiplier let dy = mass * sqrt(2 * -self.physicsWorld.gravity.dy * (fixedCircle.position.y-jumpingCircle.position.y)) * 12.3 // apply the Impulse jumpingCircle.physicsBody?.applyImpulse(CGVectorMake(0, CGFloat(dy))) } } } 

弄清楚了。

SpriteKit显然有一个没有logging的像素与“米”的比例为150。

当我意识到大量SpriteKit自动计算我的圈子时,我发现这个不是 50 * pi * r ^ 2,因为它应该是。 我从质量计算SpriteKit正在使用的半径,它是7500,恰好是50 * 150。

还有12.3? 它恰好是(大约)150的平方根。

所以要使这些物理模拟工作,你必须考虑这个比例。 我称之为“像素到单位”(PTU),因为尽pipe苹果坚持认为SpriteKit使用SI单位,但它与米无关。 但是因为它没有文档,所以似乎可以改变,所以我使用下面的代码行来开始我的模拟来确定真正的PTU:

 let ptu = 1.0 / sqrt(SKPhysicsBody(rectangleOfSize: CGSize(width:1,height:1)).mass) 

这是一个昂贵的操作,所以应该只调用一次。 我在设置初始场景时调用它。

现在我的冲动计算如下:

 let dy = mass * sqrt(2 * -self.physicsWorld.gravity.dy * (fixedCircle.position.y-jumpingCircle.position.y * ptu)) 

现在黑圈跳到与红圈完美alignment,晚上我可以回去睡觉。

而不是applyImpulse使用速度。 速度会更具体。 jumpingCircle.physicsBody?.velocity = CGVectorMake(jumpingCircle.physicsBody.velocity.dx, 300.0f); 代码未经testing。