I'm learning SpriteKit game development for the fun of it & I've run across a seemingly simple problem that has me stumped.
Basically, after I scale a textured SKSpriteNode, the frame is NOT what I expect. I have figured out a few hacks to force it to what I want, but I'm trying to understand what is going on. Any ideas appreciated!
Here's my code WITHOUT SCALING:
func addSpaceship()
{
let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png")
spaceship.name = "spaceship"
// spaceship.setScale(0.50)
let debugFrame = SKShapeNode.init(rect: spaceship.frame)
debugFrame.strokeColor = SKColor.greenColor()
spaceship.addChild(debugFrame)
spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) - 150)
self.addChild(spaceship)
}
And my app looks like this:
Now, if I comment back in the line of code which scales it (spaceship.setScale(0.50)), I get this:
Notice that the spaceship is scaled down in the second image, but the frame is scaled even smaller. Why?
If I move the scaling line to after I add the spaceship to the scene, it does what I expect, but that seems wrong:
Here's the code with setScale called after adding the spaceship to the scene:
func addSpaceship()
{
let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png")
spaceship.name = "spaceship"
let debugFrame = SKShapeNode.init(rect: spaceship.frame)
debugFrame.strokeColor = SKColor.greenColor()
spaceship.addChild(debugFrame)
spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) - 150)
self.addChild(spaceship)
spaceship.setScale(0.50)
}
And here is what running my app looks like then:
So that works, but why is it necessary?
It has been suggested below, that this is a bug with SKShapeNode. But, replacing the SKShapeNode with an SKLabelNode has the same problem:
func addSpaceship()
{
let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png")
spaceship.name = "spaceship"
spaceship.setScale(0.50)
let scoreNode = SKLabelNode(text: "100")
scoreNode.position = CGPointMake(CGRectGetMidX(spaceship.frame), CGRectGetMaxY(spaceship.frame))
scoreNode.fontColor = SKColor.redColor()
scoreNode.fontSize = 15.0
scoreNode.fontName = "Monaco"
scoreNode.zPosition = 10.0
spaceship.addChild(scoreNode)
spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) - 150)
self.addChild(spaceship)
}
which gives us:
The intent is to have the score label (scoreNode) centered above the rocket, but as you can see it is on top of the top porthole. There is just something wrong with the spaceship's frame after I call spaceship.setScale.
I have made one additional discovery: the setScale call does not need to be after I add the spaceship to the scene. It just needs to be after I add the debugFrame/scoreNode to the spaceship. If I setScale AFTER that point, all is well:
func addSpaceship()
{
let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png")
spaceship.name = "spaceship"
let scoreNode = SKLabelNode(text: "100")
scoreNode.position = CGPointMake(CGRectGetMidX(spaceship.frame), CGRectGetMaxY(spaceship.frame))
scoreNode.fontColor = SKColor.redColor()
scoreNode.fontSize = 15.0
scoreNode.fontName = "Monaco"
scoreNode.zPosition = 10.0
spaceship.addChild(scoreNode)
spaceship.setScale(0.50)
spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) - 150)
self.addChild(spaceship)
}
which results in: