1

If there a better way of creating a blur effect? It seems like the way I am currently doing it creates FPS issues especially on older phones. It seems like the higher the blurAmount the lower the FPS. Could the blendMode be the reason here?

        if effectsNode.parent == nil {
            let filter = CIFilter(name: "CIGaussianBlur")
            let blurAmount = 15.0
            filter!.setValue(blurAmount, forKey: kCIInputRadiusKey)

            effectsNode.filter = filter
            effectsNode.blendMode = .add

            sceneContent.removeFromParent()
            effectsNode.addChild(sceneContent)
            addChild(effectsNode)
        }

When I pause my game, I call blurScreen() which does the following code above. However, it seems like my fps drops over time the longer the game is paused. I tried taking blurScreen() out and the FPS issues went away. How is the FPS dropping over time when blurScreen() is only called once?

EDIT:

func pauseGame() {
    sceneContent.isPaused = true
    intermission = true

    physicsWorld.speed = 0

    blurScreen()
} 

Here is the code in touchesEnded()

// Tapped pause or pause menu options
if name == "pause" && touch.tapCount == 1 && pauseSprite.alpha == 1.0 && ((!sceneContent.isPaused && !GameData.shared.midNewDay) || (!sceneContent.isPaused && sceneElements[0].editingMode)) {
                    SKTAudio.sharedInstance.pauseBackgroundMusic()
                    SKTAudio.sharedInstance.playSoundEffect("Sounds/pause.wav")

                   pauseSprite.run(SKAction.sequence([SKAction.scale(to: 1.2, duration: 0.10), SKAction.scale(to: 1.0, duration: 0.10)])) { [unowned self] in
                        self.createPauseMenu()
                        self.pauseGame()
                    }

                    return
                }

Update method

override func update(_ currentTime: TimeInterval) {
    if GameData.shared.firstTimePlaying && GameData.shared.distanceMoved > 600 && !step1Complete {
        tutorial2()
    }

    // Check for game over
    if GameData.shared.hearts == 0 && !gameEnded {
        gameOver()
    }

    // If we're in intermission, do nothing
    if intermission || sceneContent.isPaused {
        return
    }

    // some more stuff unrelated to pausing
}
Brejuro
  • 3,421
  • 8
  • 34
  • 61
  • We need to see more code, blurring once should not cause slowdown, but blurring on the update loop will – Knight0fDragon Oct 27 '17 at 14:58
  • Also, you can always do the blur on the background thread, and when finished, add it to the parent on the main thread – Knight0fDragon Oct 27 '17 at 14:58
  • @Knight0fDragon Thanks for the reply! That's what I thought as well, I added some more code related to pausing – Brejuro Oct 27 '17 at 15:29
  • oh, you are blurring the entire scene, yeah that is going to be slow. Definitely put that in the background thread – Knight0fDragon Oct 27 '17 at 15:33
  • btw, scene is an SKEffectNode, so you should be able to apply blur directly to it – Knight0fDragon Oct 27 '17 at 15:34
  • @Knight0fDragon Do you know how I'd go about doing that or somewhere I can read up on it? I haven't done much using background threads. Also I'm blurring the contents of an SKNode called sceneContent which holds all the nodes that I need blurred, so I add sceneContent to effectsNode and blur that. There are some nodes that shouldn't be blurred which is why I don't blur the entire scene – Brejuro Oct 27 '17 at 15:36
  • oh i get you, pause is an overlay node. um no idea, but the code is `DispatchQueue.global(qos:.background).async{...do code ... DispatchQueue.main.async{..do stuff needed on main thread}}` – Knight0fDragon Oct 27 '17 at 15:41
  • @Knight0fDragon I'm going to lookup how to do tasks on background thread. Do you think this will solve the FPS issue though? – Brejuro Oct 27 '17 at 15:45
  • Yes I think, I don't see any major flaws in your code (Although I am not a fan of you doing so much branching on your update function, you should break this habit.) You just need to make sure that you are not doing anything while the effect is being created. – Knight0fDragon Oct 27 '17 at 15:47
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/157678/discussion-between-brejuro-and-knight0fdragon). – Brejuro Oct 27 '17 at 15:55

1 Answers1

0

You are running an effect node on the entire scene, that scene is going to be rendering that effect every frame which is going to put a lot of work on your system. If you do not have any animations going on behind it, I would recommend converting your effect node to a sprite node by doing this

var spriteScene : SKSpriteNode!
func blurScreen() { 
    DispatchQueue.global(qos: .background).async { 
        [weak self] in
        guard let strongSelf = self else { return }
        let effectsNode = SKEffectNode() 

        let filter = CIFilter(name: "CIGaussianBlur") 
        let blurAmount = 10.0 
        filter!.setValue(blurAmount, forKey: kCIInputRadiusKey) 

        effectsNode.filter = filter 
        effectsNode.blendMode = .add 

        strongSelf.sceneContent.removeFromParent() 
        effectsNode.addChild(strongSelf.sceneContent) 

        let texture = self.view!.texture(from: effectsNode) 
        strongSelf.spriteScene = SKSpriteNode(texture: texture) 
        strongSelf.spriteScene.anchorPoint = CGPoint(x: 0.5, y: 0.5) 

        DispatchQueue.main.async { 
            strongSelf.sceneContent.removeFromParent() 
            strongSelf.addChild(strongSelf.spriteScene) 
        } 
    } 
} 
Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44