2
votes

I have a node, A, in a parent node, B.

I'm using setScale on node B to give the illusion of zooming, but when I do that, node A and all of its siblings do not have the expected physics bodies.

Even though A appears smaller and smaller, its physics body stays the same size. This leads to wacky behavior.

How can I "zoom out" and still have sensible physics?

3
If you're using iOS9, you could use an SKCameraNode.ABakerSmith
Did you set view.showsPhysics = true? This will show an outline of the physics bodies in the node tree. I think you'll see that the size of the body does change proportionately to the node's parent. If not, I suggest you post the code that sets up the physics body.0x141E
@0x141E The node visually scales, but the physics body does not.Stefan Kendall
@ABakerSmith POST THAT AS AN ANSWER! Sounds incredibly promising, and I'll try that tonight.Stefan Kendall

3 Answers

2
votes

The SKCameraNode (added in iOS9) sounds perfect for your scenario. As opposed changing the scale of every node in the scene, you would change the scale of only the camera node.

Firstly, you need to add an SKCameraNode to your scene's hierarchy (this could all be done in the Sprite Kit editor too).

override func didMoveToView(view: SKView) {
    super.didMoveToView(view)

    let camera = SKCameraNode()
    camera.position = CGPoint(x: size.width / 2, y: size.height / 2)
    self.addChild(camera)
    self.camera = camera
}

Secondly, since SKCameraNode is a node you can apply SKActions to it. For a zoom out effect you could do:

guard let camera = camera else { return }
let scale = SKAction.scaleBy(2, duration: 5)
camera.runAction(scale)

For more information have a look at the WWDC 2015 talk: What's New In Sprite Kit.

3
votes

SKPhysicsBody cannot be scaled. As a hack you could destroy the current physics body and add a smaller one as you scale up or down but unfortunately this is not a very efficient solution.

1
votes

A simple example that shows that a physics body scales/behaves appropriately when its parent node is scaled. Tap to add sprites to the scene.

class GameScene: SKScene {

    var toggle = false
    var node = SKNode()

    override func didMoveToView(view: SKView) {
        self.physicsBody = SKPhysicsBody(edgeLoopFromRect: view.frame)
        scaleMode = .ResizeFill
        view.showsPhysics = true
        addChild(node)
        let shrink = SKAction.scaleBy(0.25, duration: 5)
        let grow = SKAction.scaleBy(4.0, duration: 5)
        let action = SKAction.sequence([shrink,grow])
        node.runAction(SKAction.repeatActionForever(action))
    }

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        /* Called when a touch begins */

        for touch in (touches as! Set<UITouch>) {
            let location = touch.locationInNode(node)
            let sprite = SKSpriteNode(imageNamed:"Spaceship")

            if (toggle) {
                sprite.physicsBody = SKPhysicsBody(circleOfRadius: sprite.size.width/2.0)
            }
            else {
                sprite.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.size)
            }

            sprite.xScale = 0.125
            sprite.yScale = 0.125
            sprite.position = location

            node.addChild(sprite)

            toggle = !toggle
        }
    }
}