Search code examples
iossprite-kitmaskskspritenodeskcropnode

Mask SKSpriteNode


I add few nodes to my sks file, and now I want to add some mask to the most lowest node SKSpriteNode. Structure is as shown below:

enter image description here

where

  • green - wordInfoHolder
  • red - container for Label
  • whiteText - label

Now I want to hide part that is shown in red. To perform such action I read that SKCropNode can be used.

I able to find all my nodes in scene file and save them to variables.

if let holder = childNode(withName: "wordInfoHolder") as? SKSpriteNode {
        wordInfoHolder = holder
        if let wordSwitchNode = wordInfoHolder?.childNode(withName:"wordSwitchNode") as? SKSpriteNode {
            self.wordSwitchNode = wordSwitchNode

            if let label = self.wordSwitchNode?.childNode(withName:"infoLabel") as? SKLabelNode {
                wordSwitchLabelNode = label
            }
       }
}

all 3 objects are stored and correct.

Now I want to add some mask to root object.

For such purpose I prepared mask image:

enter image description here

and try to do something like:

  guard let holder = wordInfoHolder else { return }
  let positionToSet = holder.position
  let mask = SKSpriteNode(imageNamed: "rectangle_mask")
  let cropNode = SKCropNode()
  holder.removeFromParent()
  cropNode.addChild(holder)
  cropNode.maskNode = mask
  cropNode.position = positionToSet
  self.addChild(cropNode)

But I see nothing. I expect to see green part of SKSpriteNode.

What was done wrong?


Solution

  • Assuming that you have set zPosition on all your objects.

    I'm quite sure the issue is that because you are moving your holder object from the scene to the cropNode it is retaining it's position info from the scene (for example if it's position in the scene was 500, 500 it's position in the cropNode is now 500, 500)

    I was able to recreate your issue and by setting the holder.position to zero the issue went away.

    In the picture below I am using the yellow box as mask and the blue and pink boxes are test objects to ensure the the cropNode is placed between them.

    enter image description here

    if let holder = self.childNode(withName: "holder") as? SKSpriteNode {
        self.holder = holder
    
        if let switcher = holder.childNode(withName: "//switcher") as? SKSpriteNode {
            self.switcher = switcher
        }
    }
    
    if let mask = self.childNode(withName: "mask") as? SKSpriteNode {
    
        mask.removeFromParent()
    
        let positionToSet = holder.position
        holder.position = CGPoint.zero
        mask.position = CGPoint.zero
    
        let cropNode = SKCropNode()
        holder.removeFromParent()
        cropNode.addChild(holder)
        cropNode.maskNode = mask
        cropNode.position = positionToSet
        cropNode.zPosition = 10
        self.addChild(cropNode)
    }
    

    added tidbit

    holder.move(toParent: cropNode)
    

    can be used in place of

    holder.removeFromParent()
    cropNode.addChild(holder)