如何使用 SpriteKit 使精灵跳到特定高度? [英] How to make a sprite jump to a specific height with SpriteKit?

查看:13
本文介绍了如何使用 SpriteKit 使精灵跳到特定高度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to use applyImpulse to make a sprite jump to a specific height. In the example code below, the dynamic black circle jumps to the same height as the static red circle, but it only works with a kludge.

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

If my physics is right, the required initial vertical momentum to launch a projectile to height Y is given by mass * sqrt(2 * gravity * Y). Yet this formula results in the black circle moving very little.

通过反复试验,我发现我可以通过将脉冲向量的垂直分量乘以 12.3 或多或少准确地使红色圆圈跳跃,如下面的代码所示.

Through trial and error, I have discovered that I can make the red circle jump more or less accurately by multiplying the vertical component of the impulse vector by 12.3, as illustrated in the code below.

这似乎完全是武断的,让我发疯.我显然做错了什么.这样做的正确方法是什么?

This seems completely arbitrary and is driving me crazy. I am obviously doing something wrong. What's the right way to do this?

以下是我认为相关的代码:

Here's what I think is the relevant bit of code:

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 类,如果您想复制和粘贴...

Here's the GameScene.swift class in its entirety, should you wish to copy and paste...

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 显然有一个未记录的像素与米"比为 150.

SpriteKit apparently has an undocumented pixel-to-"meter" ratio of 150.

当我意识到 SpriteKit 自动为我的圈子计算的质量不是应该是 50*pi*r^2 时,我发现了这一点.我从质量向后计算 SpriteKit 使用的半径,它是 7500,恰好是 50*150.

I discovered this when I realized the mass SpriteKit was automatically calculating for my circles was not 50*pi*r^2 as it should be. I worked backward from mass to calculate the radius SpriteKit was using, and it was 7500, which happens to be 50*150.

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

And 12.3? It just happens to be (approximately) the square root of 150.

因此,要使这些物理模拟发挥作用,您必须考虑这个比率.我将其称为像素到单位"(PTU),因为尽管 Apple 坚持 SpriteKit 使用 SI 单位,但它与米无关.但是因为它没有记录,所以似乎可以更改,所以我开始使用以下代码行来确定真正的 PTU:

So to make these physics simulations work, you have to consider this ratio. I'm calling it "pixel to unit" (PTU) because it has nothing to do with meters in spite of Apple's insistence that SpriteKit uses SI units. But because it's undocumented it seems possible to change, so I'm kicking off my simulation using the following line of code to determine the true PTU:

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

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

This is an expensive operation, so it should only be called once. I'm calling it when setting up the initial Scene.

我现在的冲动计算如下:

My impulse calculation is now as follows:

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

现在黑色圆圈与红色圆圈完美对齐,我可以在晚上继续睡觉.

And now the black circle jumps to perfect alignment with the red circle and I can go back to sleeping at night.

这篇关于如何使用 SpriteKit 使精灵跳到特定高度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆