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
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...