Zposition of Sknode Relative to Its Parent

zPosition of SKNode relative to its parent?

When reading the Apple Documentation regarding this, you can find:

Maintaining the order of a node’s children can be a lot of work. Instead, you can give each node an explicit height in the scene. You do this by setting a node’s zPosition property. The z position is the node’s height relative to its parent node, much as a node’s position property represents its x and y position relative to parent’s position. So you use the z position to place a node above or below the parent’s position.

When you take z positions into account, here is how the node tree is
rendered:

  • Each node’s global z position is calculated.
  • Nodes are drawn in order from smallest z value to largest z value.
  • If two nodes share the same z value, ancestors are rendered first, and siblings are rendered in child order.

The point I found - which i didn't know it was like this - is that the children zPosition is calculated summating their parents zPosition, so if node1.zPosition + (node1's)child3.zPosition = 4, and node2.zPosition + (node2's)child3.zPosition = 3, the node1's child will be painted above.

Solution: Set node2.zPosition bigger than (node1's)lastChild.zPosition + node1.zPosition.

How to position child SKSpriteNodes inside their parents

The default anchor point in SpriteKit is (0.5, 0.5), which is the center of a node/sprite. (0, 0) is bottom left corner and (1, 1) is top right corner. Look at this picture.

Sample Image

After choosing a node's anchor point, you can treat it as the origin of a coordinate system whose range is the node's frame size. The position offset is calculated/affected by both the child's anchor point and its parent's anchor point.

For example, a (red) parent node rect is (100, 100) in size and a (green) child node child is (50, 50) in size. Set the child position at (-25, 25) in parent's coordinate system will have the following result.

// parent node
let parent = SKSpriteNode(color: UIColor.redColor(), size: CGSizeMake(100.0, 100.0))
parent.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame));
self.addChild(parent)

// child node
let child = SKSpriteNode(color: UIColor.greenColor(), size: CGSizeMake(50.0, 50.0))
child.zPosition = 1
child.position = CGPointMake(-parent.size.width/4, parent.size.height/4) // (-25, 25))
parent.addChild(child)

Sample Image

More experiments of SpriteKit position and anchor point can be found here.

Can I place a children sprite below it's parent using zPosition

It should be possible, but even if it is not there's a better solution that gives you greater flexibility in the long run.

Instead of adding two child sprites to a sprite node, create a regular SKNode and add all three sprites as children to it. That way you're free to re-arrange them in whatever way you see fit, while all three will follow the position changes of their parent node.

SKSpriteNodeChild in the wrong zPosition

The problem has been fixed. I can't be 100% sure what solved it as I tried a few things. I set the ignoresSiblingOrder to false and then back to true, moved the definition of the childNode that was appearing on top into the same function as the parent, and, finally (I suspect this was the reason for the fix), moved the order of addChild and setting the zPosition (in my project, the order was originally child1.zPosition, parentNode.addChild; changing the order of these two probably fixed the problem as I suspect the subsequent sibling order was confusing the zPosition).

Different zPositions relative to different Nodes

I don't think it's possible. To show node A above B and hide A behind C means that you need C to be above both A and B. But then you need B to be higher than C, which means that C can't be above B. Try it with pieces of paper on a desk and you will see that you can't meet both objectives...

SpriteKit issue with zPosition

Here is how you are expecting your code right now

 -100: Node
# 0: Node
# 0: Blue
0 : Node
# 0: Node
# 0:Red
100 : Node
# 0: Node
# -200:Green
# -150:Yellow

But what is really happening is this

 -100: Node
: Node
: Blue
: Green
-50 : Yellow
0 : Node
: Node
: Red
100 : Node
: Node

This is because the zPosition is just subtracted from the parent, and the screen then draws in 1 pass all the nodes.

To combat this, you need to create a custom class that overrides the addChild function and do somethings that keep track of your zPosition in another variable (probably a dictionary), then set the child zPosition to zero, and use insertChild(node:, atIndex:) to place your children in order in the children array using this new variable to preserve your order. Then if you are going even more crazy, you would have to keep track of when a child changes its zPosition, and use the above style to set it correctly in the array

SpriteKit: find all descendants of SKNode of certain class?

What we did was pass a block to the SKNode function that finds nodes by name, and used * as the search term to avoid assigning a name to desired nodes.

    var descendants = [CustomClass]()
nodeToSearch.enumerateChildNodes(withName: ".//*") { node, stop in
if node is CustomClass {
descendants.append(node as! CustomClass)
}
}

Sprite-Kit : Sprite z-Order

For draw order use the zPosition property of a node:

zPosition The height of the node relative to its parent.

The default value is
0.0. The positive z axis is projected toward the viewer so that nodes with larger z values are closer to the viewer. When a node tree is
rendered, the height of each node (in absolute coordinates) is
calculated and then all nodes in the tree are rendered from smallest z
value to largest z value. 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. Hit-testing is processed in the
opposite order.

The SKView class’s ignoresSiblingOrder property controls whether node
sorting is enabled for nodes at the same z position.

You can also use insertChild:atIndex: to affect z order but keep in mind that index is the index of the object in the array, not it's zPosition (ie atIndex parameter is not the same as the z parameter in cocos2d, in fact it's the inverse). Nodes added at a lower index will be drawn before nodes at a higher index.

Also note that you can't insert nodes at an index out of bounds. From the NSMutableArray docs:

[..] you cannot insert an object at an index greater than the
current count of an array. For example, if an array contains two
objects, its size is 2, so you can add objects at indices 0, 1, or 2.
Index 3 is illegal and out of bounds; if you try to add an object at
index 3 (when the size of the array is 2), NSMutableArray raises an
exception.



Related Topics



Leave a reply



Submit