I have a UIImageView for the user to look at (looks almost like a splash screen) come up so that I can preload my texture atlases.
But it seems that in the completion block, even though I say to 'removefromsuperview' it doesn't do so.
I know that the textures have finished loading because if I tap the screen the UIImageView goes away and my game starts, but it won't go away on its own for some odd reason.
Here is my viewDidLoad inside my GameViewController:
//Configure the View
let skView = view as! SKView
skView.multipleTouchEnabled = false
self.view.exclusiveTouch = false
//Create and Configure the scene
scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
//Load "SPLASH SCREEN"
let image: UIImage = UIImage(named: "ViewControllerImage")!
GameViewController.splashView = UIImageView(image: image)
GameViewController.splashView!.frame = CGRectMake(0,0,self.view.bounds.width,self.view.bounds.height)
self.view.addSubview(GameViewController.splashView!)
SKTextureAtlas.preloadTextureAtlases([GameViewController.diploTextureAtlas,GameViewController.bieberTextureAtlas,GameViewController.skrillexTextureAtlas,GameViewController.sunTextureAtlas], withCompletionHandler: { () -> Void in
print("Completo")
GameViewController.splashView?.removeFromSuperview()
skView.presentScene(self.scene)
})
Try this code:
//Configure the View
let skView = view as! SKView
skView.multipleTouchEnabled = false
self.view.exclusiveTouch = false
//Create and Configure the scene
scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
//Load "SPLASH SCREEN"
let image: UIImage = UIImage(named: "ViewControllerImage")!
GameViewController.splashView = UIImageView(image: image)
GameViewController.splashView.tag = 666
GameViewController.splashView!.frame = CGRectMake(0,0,self.view.bounds.width,self.view.bounds.height)
self.view.addSubview(GameViewController.splashView!)
SKTextureAtlas.preloadTextureAtlases([GameViewController.diploTextureAtlas,GameViewController.bieberTextureAtlas,GameViewController.skrillexTextureAtlas,GameViewController.sunTextureAtlas], withCompletionHandler: { () -> Void in
print("Completo")
for view in self.view!.subviews {
if view.tag == 666 {
view.removeFromSuperview()
}
}
skView.presentScene(self.scene)
})
You can change for cycle also with:
if let viewWithTag = self.view.viewWithTag(666) {
viewWithTag.removeFromSuperview()
}
Related
I'm developing a game using sprite kit and have various view controllers for different scenes. Like story mode, multiplayer etc...
I've noticed a problem where every time I open up a view controller with a SpriteKit scene, the memory usage for my app increases. And when the view is dismissed, that memory isn't allocated back?
Is there something I need to be doing in my code to return the memory the ViewController or SpriteKit scene used up upon loading?
EDIT: As requested, here is some code from when the VC loads up with a SpriteKit scene & the code used to dismiss the VC:
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
if let scene = SKScene(fileNamed: "GameScene.sks") {
scene.scaleMode = .aspectFill
view.presentScene(scene)
(scene as! GameScene).parentVC = self
}
}
}
For the view dismissal, I first present a loading screen over the UIApplication.shared.keyWindow and then dismiss:
dismiss(animated: true) {
LoadingScreen?.removeFromSuperview()
}
The loading screen class is handled in the AppDelegate.
I think it's an issue of retain cycles
1 if let view = self.view as! SKView? {
2 if let scene = SKScene(fileNamed: "GameScene.sks") {
3 scene.scaleMode = .aspectFill
4 view.presentScene(scene)
5 (scene as! GameScene).parentVC = self
}
}
if line 5, inside the closure, you're referencing self, so when the viewcontroller should be deallocated, the reference on line 5 is stopping the deallocation, Can you try this :
if let view = self.view as! SKView? {
if let scene = SKScene(fileNamed: "GameScene.sks") {
scene.scaleMode = .aspectFill
view.presentScene(scene)
guard let scene = scene as? GameScene else { return }
guard let scencePVC = scene.parentVC else { return }
scencePVC = self
}
}
I'm trying to fix the issue without knowing the object hierarchy but it's hard. Basically the issue is that you have 2 objects( viewcontrollers) referencing each other that would stop the deallocation.
You can read more about this issue here & here
How do I make it so that the scene does not change until after both of those functions a finished?
Thanks
Code:
let location = touch.locationInNode(self)
if self.nodeAtPoint(location) == self.playButton {
PlayPressDown()
PressedPlay()
println(" PlayBtn Going to game play.")
var scene = SecondScene(size: self.size)
let sKView = self.view! as SKView
sKView.ignoresSiblingOrder = true
scene.size = sKView.bounds.size
let reveal = SKTransition.fadeWithDuration(1.1)
sKView.presentScene(scene, transition: reveal)
Don't link your button directly to a segue. Link it to an IBAction. Write code in your IBAction that does what you want, then invokes the segue using performSegueWithIdentifier after your steps are complete.
I'm creating a game using Sprite Kit. I have my GameScene and GameOverScenenow I want to create a MenuScene Where do I control the order of the MenuScene so that it shows up after LaunchScene
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene.unarchiveFromFile("MenuScene") as? GameScene {
// Configure the view.
let skView = self.view as! SKView
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
Edit tried putting ("MenuScene") as the scene but when I run the game that scene won't show
Ok so I found out that I was one the right path. I just needed to change this line. Instead of this
if let scene = GameScene.unarchiveFromFile("MenuScene") as? GameScene {
add this
if let scene = MenuScene.unarchiveFromFile("MenuScene") as? MenuScene {
I am programming a game but I have one problem. I have two scenes. (1. GameScene 2. PlayScene). The GameScene displays the PlayButton. If you press the PlayButton the PlayScene will be displayed. The PlayScene displays the game. If you lose the Game, the GameScene will be presented again.
GameScene --> PlayScene --> GameScene
This is the code, which is in the GameScene and presents the PlayScene.
if self.nodeAtPoint(location) == self.playButton { // Wenn position des klicks gleich mit position des play button
println("Go to the game")
var scene = PlayScene(size: self.size)
let skView = self.view! as SKView
skView.ignoresSiblingOrder = true
scene.scaleMode = .ResizeFill
scene.size = skView.bounds.size
skView.presentScene(scene)
}
This is the code, which is in the PlayScene and presents the GameScene again.
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
let skView = self.view as SKView!
skView.ignoresSiblingOrder = true
scene.size = skView.bounds.size
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
My Problem is that the GameScene has first a different size than the GameScene which is presented after the PlayScene. I can't show photos because I don't have 10 reputations -.-, but I can explain it. For example: The PlayButton in the GameScene, which is presented after the program starts, is smaller than the PlayButton, which is presented in the GameScene after the PlayScene is presented.
I tried to change the scaleModes but that didn't work.
Here are the links for the photos, which show my problem.
This is the "second" GameScene presented:
https://drive.google.com/open?id=0B57TI4Xur5Fldy1EcVh6NmVIdm8&authuser=0
This is the "first" GameScene presented:
https://drive.google.com/open?id=0B57TI4Xur5FlR3ZXT2NFSEZRZHc&authuser=0
The issue could be that you aren't using the same settings as you are for the first scene. Try this.
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
let skView = self.view as SKView!
skView.ignoresSiblingOrder = true
scene.size = self.size
scene.scaleMode = self.scaleMode
skView.presentScene(scene)
}
Thank you but it didn´t worked. I tried some other changes and it worked but I don´t know why.
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
let skView = self.view as SKView!
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
Now both Scenes have the same size.
If I print self.size i get (320,480) but it should be (480,320) because my app is in landscape this is how I go to my main view:
var playScene = Menu(size: self.size)
let skView = self.view! as SKView
skView.ignoresSiblingOrder = true
playScene.scaleMode = .ResizeFill
playScene.size = skView.bounds.size
skView.presentScene(playScene)
Edit: I've found that on an Iphone 5s the self.size is (568, 320) so the problem is only on iphone 4s or on IOS 7
The sizes of views aren't updated until UIKit runs layout. That happens after viewDidLoad returns. So if that code is in viewDidLoad, you're checking too soon. Look at the size in viewDidLayoutSubviews or viewDidAppear:.
I've had to use this function to get the right screen size for the device i am using:
func screenSize() -> CGSize {
var screenSize: CGSize = UIScreen.mainScreen().bounds.size
if ((NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) && UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation)) {//If ios 7
return CGSizeMake(screenSize.height, screenSize.width);
}
return screenSize;
}
And i replace my code to change the view to:
var playScene = Menu(size: self.size)
let skView = self.view! as SKView
skView.ignoresSiblingOrder = true
playScene.scaleMode = .ResizeFill
playScene.size = screenSize()
skView.presentScene(playScene)