I have a very weird situation where an SKShapeNode created from a polygon is not showing up when it is added to an SKSpriteNode, but working fine on the base SKScene. (Update - it is solved, see end of question)
As part of the debugging, I attached another SKSpriteNode to the SKShapeNode, to show another image on top.
That second image always appears.
So the working hierarchy is:
- SKScene
- SKShapeNode - blue shape
- SKSpriteNode - Ant picture
- SKShapeNode - blue shape
Whitespace cropped on this first picture - the Ant is in the same location in both.
The non-working hierarchy is:
- SKScene
- SKSpriteNode - foot picture
- SKShapeNode - blue shape (not drawn but its attached Ant is)
- SKSpriteNode - Ant picture
- SKShapeNode - blue shape (not drawn but its attached Ant is)
- SKSpriteNode - foot picture
Here is hopefully enough of the code to help someone work out what's happening. Note that:
- It is not a side-effect of using the points array to construct the drawing - the same thing happens if I create a simple rect shape using either the
init(rect:)
orinit(rectOf:)
- It happens on both device and simulator.
Update after scaling to debug, as suggested in comments
Scene background set to red to make it clear.
Thanks for any suggestions, I'm at my wits-end here.
the code to attach the drawing and ant pic to a node
override func applyTo(node:SKNode) -> Bool {
var pointsVec = renders[0].rescaledPoints().map{ tp in tp.loc }
let numPointsNow = pointsVec.count
if numPointsNow==0 {
return false
}
let draw = SKShapeNode(points: &pointsVec, count: numPointsNow)
draw.lineWidth = 1
draw.fillColor = fillColor
draw.strokeColor = fillColor
draw.position = CGPoint(x: 0, y: 0)
node.addChild(draw)
let antNode = SKSpriteNode(imageNamed: "Ant05_150px.png")
antNode.position = CGPoint(x:0.0, y:0.0) // for anchor 0,0
antNode.size = CGSize(width: node.frame.width, height: node.frame.height)
antNode.anchorPoint = CGPoint(x: 0.0,y: 0.0)
draw.addChild(antNode)
return true
}
factory function making the SKSpriteNode used for the foot
override func makeBackgroundNode(_ within:CGSize) -> SKNode? {
let bgNode = SKSpriteNode(imageNamed: imageName)
bgNode.size = within
bgNode.position = CGPoint(x:0.0, y:0.0) // for anchor 0,0
bgNode.anchorPoint = CGPoint(x: 0.0,y: 0.0)
return bgNode
}
scene factory using the makeBackground
func makeSKScene(_ within:CGSize) -> SKScene? {
let scene = tgSKSceneWithTouch(size: within)
playingBounds = within
var rootNode : SKNode = scene
if let bg = currentScene?.background {
if let bgNode = bg.makeBackgroundNode(within) {
scene.addChild(bgNode)
rootNode = bgNode
}
...
currentScene?.applyTo(sourceOfTouches:scene, nodeToAttachChildrenTo:rootNode)
// iterates down through non-SpriteKit logic to invoke the applyTo
}
The Answer
Explicitly setting zPosition in applyTo
fixes it!
draw.zPosition = node.zPosition + 1
node.addChild(draw)
This seems in direct contradiction to the docs
If multiple nodes share the same z-position, those nodes are sorted so that parent nodes are drawn before their children, and siblings are rendered in the order that they appear in their parent’s children array.
Leading me to the conclusion that either the default zPosition for a shape node is different or this mechanism is not applying here for some other reason! (Maybe because of change of node type?)
applyTo
get called? – Knight0fDragon