Search code examples
sprite-kitskemitternode

How to contain SKEmitterNode particles in parent Node?


I would like to add a SKEmitterNode to SKNode but have its particles stay inside the parent node's frame. Kinda like clipsToBounds property on UIView.

Example: the particles from the emitter should not leave the black square SKSpriteNode:

enter image description here


Solution

  • You could do it with SKCropNode. Like this:

    if let particles = SKEmitterNode(fileNamed: "rain.sks") {
    
                let cropNode = SKCropNode()
                cropNode.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
                cropNode.zPosition = 3
    
                cropNode.maskNode = SKSpriteNode(color: SKColor.blackColor(), size: CGSize(width: 150, height: 150))
                cropNode.addChild(particles)
    
                addChild(cropNode)
    
            }
    

    Unfortunately this works only on iOS8... When you try to add an emitter into crop node in iOS9, you will probably run into some issues, eg. nothing will be rendered and fps drop may occur. And this is already known issue.

    Like it's said in that link, instead of particles being rendered, nothing actually happens. Personally, I haven't experienced fps issues , but particles are definitely not rendered.

    A workaround would be to add a node which will hold an emitter, and then mask that container node. So, let's add an SKSpriteNode to make that black background like from your example. Let's call it background:

    if let particles = SKEmitterNode(fileNamed: "rain.sks") {
    
            let cropNode = SKCropNode()
            cropNode.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
            cropNode.zPosition = 3
    
            let blackNode = SKSpriteNode(color: .blackColor(), size: CGSize(width: 200, height: 200))
            blackNode.addChild(particles)
    
            cropNode.maskNode = SKSpriteNode(color: SKColor.blackColor(), size: CGSize(width: 200, height: 200))
    
            cropNode.addChild(blackNode)
    
            addChild(cropNode)
    
        }