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

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

问题描述

我想使用applyImpulse做一个精灵跳跃到一个特定的高度。在下面的例子中code时,动态黑圆跳跃到相同的高度的静态红圈,但它仅具有一个组装机的工作原理。

如果我的物理是正确的,所需要的初始垂直的势头,推出以高Y质量* SQRT(2 *重力* Y)给出的弹丸。然而,在黑色圆圈此公式会产生运动很少。

通过试验和错误,我们已经发现,我可以由12.3使红色圆圈跳或多或少准确的脉冲向量的垂直分量相乘,如下面的code示出。

这似乎完全是主观和逼我疯了。我明明做错了什么。什么是做到这一点的正确方法?

这就是我想为code的相关位:

 让DY =质量* SQRT(
    2 * -self.physicsWorld.gravity.dy
    *(fixedCircle.position.y-jumpingCircle.position.y))
    * 12.3jumpingCircle.physicsBody?.applyImpulse(CGVectorMake(0,CGFloat的(DY)))

下面是完整的GameScene.swift类,你应该要复制和粘贴...

 进口SpriteKit类GameScene:SKScene {VAR jumpingCircle = SKShapeNode()
VAR fixedCircle = SKShapeNode()覆盖FUNC didMoveToView(查看:SKView){    self.scaleMode = .AspectFit    //创建一个外部物理边界
    self.physicsBody = SKPhysicsBody(edgeLoopF​​romRect:self.frame)
    self.physicsWorld.gravity = CGVectorMake(0,-5);
    //创建跳圈
    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)
    //创建固定圈
    fixedCircle = SKShapeNode(circleOfRadius:50)
    fixedCircle.position = CGPoint(X:100,Y:384)
    fixedCircle.strokeColor = .redColor()
    self.addChild(fixedCircle)}覆盖FUNC touchesEnded(触摸:设置< NSObject的>中withEvent事件:的UIEvent){    //要达到一定的高度,的初始y速度应由开方(2 *重力* Y)
    //达到这一速度需要动量是质量*速度
    //因此,垂直冲击应该由质量*给出的sqrt(2 *重力* Y)    如果让质量= jumpingCircle.physicsBody?.mass {
        //计算纵向冲动        //这个公式应该工作,但不
        //让DY =质量* SQRT(2 * -self.physicsWorld.gravity.dy *(fixedCircle.position.y-jumpingCircle.position.y))        //这个公式作品,但任意乘数
        让DY =质量* SQRT(2 * -self.physicsWorld.gravity.dy *(fixedCircle.position.y-jumpingCircle.position.y))* 12.3        //应用脉冲
        jumpingCircle.physicsBody?.applyImpulse(CGVectorMake(0,CGFloat的(DY)))
     }
     }
 }


解决方案

想通了。

SpriteKit显然有一个未公开的像素用于─米的150比值

我发现这一点的时候,我意识到大众SpriteKit被自动计算我的圈子是的的50 * PI * R ^ 2所应当的。我从群众落后的工作来计算半径SpriteKit使用,它是7500,这恰好是50 * 150。

和12.3?这恰好是(约)150的平方根。

因此​​,为了使这些物理模拟工作,你必须要考虑这个比例。我把它称为像素单元(PTU),因为它无关,与米,尽管该SpriteKit采用国际单位制苹果的坚持。但由于它是无证似乎有可能改变,所以我用code以下行以确定真正的PTU拉开我的模拟:

 让PTU = 1.0 /开方(SKPhysicsBody(rectangleOfSize:CGSize(宽:1,身高:1))质量)

这是一项昂贵的操作,所以它应该只被调用一次。设置初始场景,当我打电话吧。

我的冲动计算如下内容:

 让DY =质量* SQRT(2
    * -self.physicsWorld.gravity.dy
    *(fixedCircle.position.y-jumpingCircle.position.y
    * PTU))

而现在的黑圈跳到完善与红色圆圈排列,我可以回去,晚上睡觉。

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.

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.

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)))

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)))
     }
     }
 }

解决方案

Figured it out.

SpriteKit apparently has an undocumented pixel-to-"meter" ratio of 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.

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

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天全站免登陆