Sprite Kit物理引擎的resting behavior属性

7

我正在使用Swift和Sprite Kit在XCode Beta 6上开发游戏。为了检测所有节点是否处于休眠状态,我检查它们的physicsBody.resting属性。在update方法中,我打印出结果。

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

    var hero:SKSpriteNode!

    override func didMoveToView(view: SKView) {
        self.physicsWorld.gravity = CGVectorMake(0, 0)
        self.physicsWorld.contactDelegate = self
        self.physicsBody = SKPhysicsBody(edgeLoopFromRect:self.frame)


        hero = SKSpriteNode(imageNamed: "Spaceship")
        hero.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
        hero.zPosition = 10.0
        hero.physicsBody = SKPhysicsBody(circleOfRadius: hero.size.width/2)
        hero.physicsBody.allowsRotation = false
        hero.physicsBody.linearDamping = 0.5
        self.addChild(hero)
    }

    override func update(currentTime: CFTimeInterval) {
        if hero.physicsBody.resting {
            println("resting")
        } else {
            println("moving")
        }
    }
}

我很惊讶,结果是这样的:
移动 休息 移动 (重复n次) 移动 休息
那么为什么英雄会移动,尽管我没有做任何事情。节点移动N次并休息一下,之后继续移动。
有人能解释这种行为吗?这是一个错误还是我漏掉了什么?提前谢谢。
1个回答

14

如果您检查物理体的速度,您会发现它正在移动,但速度非常难以感知。这就是为什么休息属性没有设置的原因。检查SKPhysicsBody是否处于静止状态的更可靠方法是测试其线性和角速度是否接近于零。以下是如何执行此操作的示例:

func speed(velocity:CGVector) -> Float {
    let dx = Float(velocity.dx);
    let dy = Float(velocity.dy);
    return sqrtf(dx*dx+dy*dy)
}

func angularSpeed(velocity:CGFloat) -> Float {
    return abs(Float(velocity))
}

// This is a more reliable test for a physicsBody at "rest"
func nearlyAtRest(node:SKNode) -> Bool {
    return (self.speed(node.physicsBody.velocity)<self.verySmallValue
        && self.angularSpeed(node.physicsBody.angularVelocity) < self.verySmallValue)
}

override func update(_ currentTime: TimeInterval) {
    /* Enumerate over child nodes with names starting with "circle" */
    enumerateChildNodesWithName("circle*") {
        node, stop in
        if (node.physicsBody.resting) {
            println("\(node.name) is resting")
        }
        if (self.nearlyAtRest(node)) {
            println("\(node.name) is nearly resting")
        }
    }
}

谢谢您的回复。您的方法看起来很棒。我正在开发一个回合制游戏,需要网络连接。这种方式也可靠吗?因为我必须确保每个玩家设备上显示的球的位置是相同的。 - Sifeng
是的,它可以与在网络上进行的游戏一起使用。 - 0x141E
我相信sqrtf(dxdx+dy+dy)应该是sqrtf(dxdx+dy*dy)。 - Ty Jacobs
只是一个小注释 - 调用 sqrtf 是不必要的,因为你可以将结果与 verySmallValue 的平方进行比较(这可以预先计算)。 - James
各位:在这种情况下,一个合理的verySmallValue是多少?因为我的速度和角速度检查显示为0.0。 - Kashif
显示剩余2条评论

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