Reputation: 166
I am making an iOS game using Swift. At the menu (Menu is a SKScene), I have a button that starts the game, let's call it 'start button'. When I hit the start button, application freezes and loads the gameplay (gameplay is a SKScene), then transition animation runs and gameplay begins. But instead of the freeze of the application, I want a rotating loading circle while application loads the gameplay. How can I do that? Ask me if there is something not clear...
func loadingScreen(scene:SKScene) {
var loadingSprite = SKSpriteNode(imageNamed: "loading.png")
loadingSprite.size = CGSize(width: 100, height: 100)
loadingSprite.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
loadingSprite.zPosition = 10
self.addChild(loadingSprite)
loadingSprite.runAction(SKAction.repeatActionForever(SKAction.rotateByAngle(3, duration: 0.5)))
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.view!.presentScene(scene, transition: SKTransition.fadeWithDuration(1.0))
})
})
}
And it is the secondScene's initializer;
convenience init (size:CGSize,mode:String) {
self.init(size:size)
self.gameMode = mode
loadItems() //loads my custom objects
printSlider() // printing sprites depending to my objects
}
Upvotes: 2
Views: 942
Reputation: 33968
Here is how I handle loading a scene in my game. I add a node to the menu scene and apply an action to it to keep it animating. I then initialize my scene on the background thread so that the main thread doesn't get blocked (remember the main thread handles visual rendering). Finally, after the scene finishes loading, I present the scene back on the main thread. Here is the code for it below.
let loadingSprite = YourLoadingSprite()
self.sceneView.scene!.addChild(loadingSprite)
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
self.gameScene = GameScene()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.sceneView.presentScene(self.gameScene, transition: SKTransition.fadeWithDuration(1.0))
})
})
Update
In your code you are not initializing the scene on the background thread. Your scene is already initialized when this method is called. You need to initialize your scene in this method but dispatch it onto the background thread. In the code below I put a comment showing your where you should initialize your scene.
func loadingScreen() {
var loadingSprite = SKSpriteNode(imageNamed: "loading.png")
loadingSprite.size = CGSize(width: 100, height: 100)
loadingSprite.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
loadingSprite.zPosition = 10
self.addChild(loadingSprite)
loadingSprite.runAction(SKAction.repeatActionForever(SKAction.rotateByAngle(3, duration: 0.5)))
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
//Initialize the scene here!
let scene = YourScene()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.view!.presentScene(scene, transition: SKTransition.fadeWithDuration(1.0))
})
})
}
Upvotes: 1
Reputation: 4177
Start the loadup code in a background thread (performSelectorInBackground), then show the animation from the main thread. The background thread will do its thing while the animation runs in parallel.
The background thread cannot directly update the animation, but it can periodically call the main thread (performSelectorOnMainThread) and have the main thread make updates.
When the background thread is done, call a mainthread function (performSelectorOnMainThread) that tells it to stop the animation and proceed with the next scene.
A similar questions that may be helpful: updating UIProgressBar progress during loop
Upvotes: 0