Search code examples
swiftsprite-kitskspritenodeskscene

Swift: Multiple scenes in Sprite Kit, touchesBegan from different SpriteNodes types on 2nd and 1st scene are called


I am facing a problem using multiple scenes in Sprite Kit (Swift). I’ve setup 3 scene (the game scene, preferences and a help scene). I’ve defined two different SpriteNode classes, called CardItem and MenuItem. While I am using CardItem just at the game scene, I uses MenuItem at all three scenes. So when I touch at the game scene (standard scene) the CardItem SpriteNode, just the touchesBegan function from that class (in game scene) is called. But when I jump into the preferences or help scene (from the game scene), and touch on a SpriteNode MenuItem not just their touchesBegan functions is called but also the touchesBegan from the CardItem type at the game scene!!! (which still is available in the back) is called.

My question is now, is this a feature or a bug in my app?

Here my GameScene Class with the scene initialization

class GameScene: SKScene, PreferencesSceneDelegate, HelpSceneDelegate {
var prefView: SKView?
var helpView: SKView?
var activeGame: Game?
var gamePrefs =  gamePreferences()
var prefManager: PreferencesManager!

func prefSceneDidFinish(myScene: PreferencesScene, command: String) {

    // Remove PreferencesScene from Screen

    if (command == "Abbruch") {
        myScene.view!.removeFromSuperview()
        setButtonTexture(command)
    } else if command == "Done" {
        myScene.view!.removeFromSuperview()
        activeGame!.setupNewGame(self, gamePrefs: self.gamePrefs, prefManager: self.prefManager, command: 1)
    } else {
        println("prefSceneDidFinish: command \(command) not specified")
    }
}


func helpSceneDidFinish(myScene: HelpScene) {

    // Remove HelpScene from Screen
    myScene.view!.removeFromSuperview()
}


override func didMoveToView(view: SKView) {
    let background = Card(cardType: .background)
    background.cardID = CardName.background.rawValue
    background.anchorPoint = CGPoint(x: 0.5, y: 1.0)
    background.position = CGPoint(x: size.width/2, y: size.height)
    background.zPosition = -2
    background.userInteractionEnabled = false
    self.addChild(background)

    //
    // Preferences Initialization
    //
    self.prefView = SKView(frame: CGRectMake(0, 0, self.frame.width, self.frame.height))

    // Create and configure PreferencesScene
    prefscene = PreferencesScene(size: view.bounds.size)
    prefscene.scaleMode = .AspectFill
    prefManager = PreferencesManager(prefs: gamePrefs)
    tmpSeriesSelection = gamePrefs.inScope // Initialize after data load fromn file

    self.prefView!.presentScene(prefscene)
    prefscene!.thisDelegate = self

    // 
    // Help Initialization
    //
    self.helpView = SKView(frame: CGRectMake(0, 0, self.frame.width, self.frame.height))

    // Create and configure HelpScene
    helpscene = HelpScene(size: view.bounds.size)
    helpscene.scaleMode = .AspectFill

    self.helpView!.presentScene(helpscene)
    helpscene!.thisDelegate = self
    var helpSceneBackground = SKSpriteNode(imageNamed: "HelpSceneBackground.png")
    helpSceneBackground.anchorPoint = CGPoint(x: 0.5, y: 1.0)
    helpSceneBackground.position = CGPoint(x: size.width/2, y: size.height)
    helpSceneBackground.zPosition = 0
    helpSceneBackground.userInteractionEnabled = false
    helpscene.addChild(helpSceneBackground)


    activeGame = Game(scene: self, gamePrefs: gamePrefs, prefManager: prefManager)
}

Here is the code snippet (MenuItem touchesBegan) where I call the scenes

    case .help :
        println("Pressed Help")
        var transition = SKTransition.fadeWithDuration(Double(0.0))
        self.scene!.view?.addSubview(gamescene.helpView!)
    case .preferences :
        …
       var transition = SKTransition.fadeWithDuration(Double(0.0))
        self.scene!.view?.addSubview(gamescene.prefView!)
    case .ok :
        println("OK Selektion")
        …
       gamescene.prefManager.save(gamescene.gamePrefs)
        prefscene.thisDelegate!.prefSceneDidFinish(prefscene, command: "Done")

Thanks in advance for your help


Solution

  • You are bound to run into problems when your scenes create their own SKView-instances which presents scenes, which creates views, which creates scenes etc. So, skip your prefView and helpView properties and use the scene's view property to present your scenes one after another.

    view?.presentScene(scoreScene)
    

    If (for some reason) you need to retain(1) the different scene-instances handle this in your GameViewController instead.

    (1) In most cases you probably shouldn't...