Make a SKLabelNode in spritekit appear above all other sprites - sprite-kit

Hi im pretty new to programming and I have encountered a small issue. I am creating a simple game which has a score label. However, the score label is covered whenever a downward scrolling obstacle passes. I would like for the score label to not be covered by the obstacles.Is there a way i can change the sprite hierarchy in spritekit? Thanks

I would recommend creating a node for the static stuff that should be fixed on screen (like a game HUD). Then you set this node's zPosition to be higher then the game play node (where all game objects are placed and manipulated).
This makes it also easier implementing a camera or moving the game play node if needed without the score label or any other fixed hud element moving as well.
So you will have something like this :
SKNode *hudNode = [SKNode node];
hudNode.zPosition = 1000;
[hudNode addChild:scoreLabel];
SKNode *gamePlayNode = [SKNode node];
gamePlayNode.zPosition = 0; // Not mandatory as it defaults to 0 but I put this here for clarification
[self addChild:hudNode]; // self is your scene instance
[self addChild:gamePlayNode];

You can change the zPosition property of your label node, by making it 100 it will be above all other nodes (default value is 0.0):
labelNode.zPosition = 100;

Nodes are drawn in the order they are added to the scene (or parent node). You can change the order in which nodes are drawn by setting their zPosition property.
From Apple's documentation...
...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.
You can also use zPosition to optimize rendering performance...
...it might be better if Sprite Kit could gather all of the nodes that share the same texture and drawing mode and and draw them with a single drawing pass. To enable these sorts of optimizations, you set the view’s ignoresSiblingOrder property to YES.

Related

Swift SceneKit issue with node position on preview

I'm trying to add nodes to my scene view, but all of the nodes have a zero position, but different placements.
Each node has a position (0,0,0) but, on the scene view, this node has a different placement. Also, I can`t find the distance between nodes because each node has a position (0, 0, 0). Please explain to me what is wrong with my nodes.
If you want to fetch the real position of a node try this:
node.presentation.worldPosition
This should always return you the effective position of the node as seen on screen.
The problem was in 3d object, the original position of the 3d was not centered. I upload each 3c object to Blender and change original position to (0,0,0)

High SpriteKit draw count with SKSpriteNode & texture atlas

I have a SpriteKit game in which there are balls that bounce around. Despite using a texture atlas (a .spriteatlas folder located in my .xcassets folder), I'm getting 2 draw calls for each ball.
Some facts:
The balls are SKSpriteNode's.
Each ball is a parent node that has a child node (an overlay with the opposite rotation of the ball to provide the illusion of lighting/shadow). So, we're talking about 2 nodes for each ball.
The balls' textures are preloaded up front and stored in memory via textureNamed(_:).
I have set view.ignoresSiblingOrder = true.
There is no SpriteKit background image that would make the balls render on top of another node; the background is transparent. So, the balls do not overlap other content.
zPosition is not set -- not on the parent and not on the child.
Based on what I've learned about how the scene is rendered, I would expect to see all the parent nodes rendered in a single pass, with additional passes for the child nodes (though, even that is suspicious since I have ignoresSiblingOrder set to true).
What am I not understanding, here? Why does my draw count increase so drastically as more balls are added to the scene?
Thank you!
UPDATE:
If I don't add the child nodes to the balls, the draw count for the balls is 1 regardless of how many balls there are. So, it's definitely an issue with the child nodes, not the parents.
I solved the problem by setting zPosition to the same value on both the parent and child.
parentNode.zPosition = 1.0
childNode.zPosition = 1.0
There are now a total of 2 draws for the balls regardless of how many balls there are.

SpriteKit sprite position inside node tree

Currently working on a simple 2D game, where I have player character that is split into multiple sprites (head, torso, legs, arms,...).
I have absolute coordinates right in Aseprite (if I take individual sprite and position them I get correct coordinates).
When I put everything into swift and use negative y instead of positive everything gets totally weird.
For example in Aseprite I have coordinates as follow: head (30, 17), torso (30, 24) and legs (28, 35). Everything aligns perfectly.
In SpriteKit I extend SKNode class and put every subsprites inside with just negative number for y. So instead of going up, I draw down. It looks like that coordinates give in pixels are not correct - sprites are off by few pixels. Mostly is off y coordinate but in some cases (character rotation) also x.
How to get from those absolute upper-left coordinates to correct SpriteKit coordinates then?
Ok I figured what was wrong (several things):
your parent class can be SKNode, but children has to have set anchor point at (0,1)
when changing texture of child sprite, always make sure that sprite size is set to new size of texture. If not it will use previous texture size and resize new texture to old size. This introduces additional problems with positioning. So you have to call: child.size = child.texture!.size() (I used force unwrap because I set (new) texture one step before so I'm 100% sure it exists.
when setting new texture set anchor point again (it seems it gets reset when changing texture of child sprite).

Clipping node to camera for only one axis

I would like to have a node in the scene, that is somehow clipped to camera node only for y axis. So that when camera moves, this node stays at the same y but moves in x and z with the rest of the scene. Is there some special way I could do something like this, or is the only way to movie the node every time camera moves?
You can use SCNTransformConstraint to have a blocked called at every frame that takes the node's transform and returns a new transform that satisfies your criteria.
There are conversion utils such as convertPosition:toNode: that will allow you to have the node's position in the coordinate system of the camera, and then back to coordinate system of the node's parent after you modified the y coordinate. Just remember to use the presentation nodes if there are animations, actions or physics in your scene.

How to stop SKSpriteNodes changing zPosition on touch

I am having an issue with the zPosition undesirably changing when a node is touched.
I can't give a simple code example because currently my scene and rendering is quite complex. Everything is drawn correctly when the scene is presented and for the most part besides as described below it works.
So the issue explained - we have a base image node correctly rendered below a tower node (tower defence game). The tower is circular and the base image is square, so the corners stick out. If you manage to touch the corners, for some reason beyond my knowledge, the zPosition changes to above the tower.
There is no particular code on touches to change any zPositions of anything in the game.
I know this is a shot in the dark, but any insight would be great and much appreciated.
If your view's ignoreSiblingOrder property is set, you should set the zPosition of each node, appropriately, to ensure that they are drawn in the correct order.
From Apple's documentation...
The default value (of SKView's ignoreSiblingOrder property) is NO,
which means that when multiple nodes share the same z position, those
nodes are sorted and rendered in a deterministic order. Parents are
rendered before their children, and siblings are rendered from eldest
to youngest. When this property is set to YES, the position of the
nodes in the tree is ignored when determining the rendering order.
The rendering order of nodes at the same z position is arbitrary and may change every time a new frame is rendered [emphasis added].