Skspritenode Gets Hidden Below Parent Node

SKSpriteNode gets hidden below parent node

What you're looking for is the ignoresSiblingOrder property on SKView:

A Boolean value that indicates whether parent-child and sibling
relationships affect the rendering order of nodes in the scene.

The default Xcode 6.x (and maybe 5, I haven't checked) SpriteKit template sets that to true when setting up the SKView in the view controller. With it set to true, the order that you add nodes to the scene does not affect their z-position. If you set it to false, they'll be layered in the order you add them to the scene (or parent node).

That being said, SpritKit can do some optimizations when ignoresSiblingOrder is true (which is why that's the default in the template), so it's probably best to keep it that way if at all possible. In that case, you'll have to manually set the zPosition property of each node though.

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.

Sprite Kit: can not see existing node's children

You are forgetting that the coordinate system of a node's child is different than that of the parent. Your parent node's "worldNode" position might be at x:500, y:500 and adding a child 20 points on top of the parent is going to x:0 y:20.

You are adding the child by using worldNode coordinates and not parent coordinates.

Child node not keeping same physicsBody when added to parent

I'm not sure if it is a bug in the Scene editor, but adding the physics bodies programmatically yields results as expected.

Some interesting things worth noting are:

the physicsBodies moved with the parent regardless of if they were not Dynamic or not.

I could not get them to overlap each other until I made them all have the same contactTestBitMask

It is difficult to tell in the screen shot but all 3 children kept their physics shapes

If the parent has a physics body and an physics impulse is applied to it, only the parent moves. However setting the position of the parent programmatically moves the parent and child nodesSample Image

    testObject = SKSpriteNode(texture: nil, color: .greenColor(), size: CGSize(width: 100, height: 100))
testObject.zPosition = Layer.Controls.rawValue
testObject.position = CGPoint(x: self.size.width / 2, y: self.size.height / 2)
// testObject.physicsBody = SKPhysicsBody(circleOfRadius: testObject.width / 2)
// testObject.physicsBody!.dynamic = true
// testObject.physicsBody!.affectedByGravity = false
// testObject.physicsBody!.allowsRotation = true
addChild(testObject)

let testerObject = SKSpriteNode(texture: nil, color: .clearColor(), size: CGSize(width: 100, height: 100))
testerObject.zPosition = Layer.Controls.rawValue
testerObject.position = CGPoint(x:50, y: 50)

testerObject.physicsBody = SKPhysicsBody(circleOfRadius: testerObject.width / 2)
testerObject.physicsBody!.affectedByGravity = false
testerObject.physicsBody!.dynamic = true
testerObject.physicsBody!.allowsRotation = true
testerObject.physicsBody!.collisionBitMask = 0
testerObject.physicsBody!.contactTestBitMask = 0

testObject.addChild(testerObject)

let testerObject2 = SKSpriteNode(texture: nil, color: .clearColor(), size: CGSize(width: 100, height: 100))
testerObject2.zPosition = Layer.Controls.rawValue
testerObject2.position = CGPoint(x:-50, y: -50)

testerObject2.physicsBody = SKPhysicsBody(circleOfRadius: testerObject.width / 2)
testerObject2.physicsBody!.affectedByGravity = false
testerObject2.physicsBody!.dynamic = true
testerObject2.physicsBody!.allowsRotation = true
testerObject2.physicsBody!.collisionBitMask = 0
testerObject2.physicsBody!.contactTestBitMask = 0
testObject.addChild(testerObject2)

let testerObject3 = SKSpriteNode(texture: nil, color: .clearColor(), size: CGSize(width: 100, height: 100))
testerObject3.zPosition = Layer.Controls.rawValue
testerObject3.physicsBody = SKPhysicsBody(circleOfRadius: testerObject.width / 2)
testerObject3.physicsBody!.affectedByGravity = false
testerObject3.physicsBody!.dynamic = true
testerObject3.physicsBody!.allowsRotation = true
testerObject3.physicsBody!.collisionBitMask = 0
testerObject3.physicsBody!.contactTestBitMask = 0
testObject.addChild(testerObject3)

Unable to hide/unhide the SKSpriteNode

If I catch what you mean, you want to show startSprite when a title is pressed (whose name is normal, and hide startSprite when other place except the title is pressed. I suggest you give every node a name before adding it to the scene. In this way, it is easier to tell which thing you've touched. Hope this will help:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {        
for touch in touches {
let location = touch.locationInNode(self)
let touchNode = self.nodeAtPoint(location)

if touchNode.name == "normal" {
startSprite.hidden = false
} else {
startSprite.hidden = true
}
}
}

Swift SKSpriteNode will disappear but is still clickable

It is because your check for which button is pressed does not take into account whether the button is visible.

Even if a node has been removed from its parent, it still has a position and size. Those two properties are used by containsPoint: to determine if a point is in a node

The easiest way to fix it would be to just check if the button has a parent node before checking to see if the button contains the point.

if InventoryButton.parrent != nil && InventoryButton.containsPoint(touch.locationInNode(self)) {
print("Show Inventory")
ShowInventory()
}


Related Topics



Leave a reply



Submit