0

I have a sprite kit game and I want to show interstitial ad when the game is over. Well, I am able to show the ad after when the game over using NotificationCenterbut the problem is that when the I close the ad, it returns to the WelcomeScene. I want to return to the GameOverScene after closing the ad but how? GameViewController.swift

import UIKit
import SpriteKit
import GameplayKit
import GoogleMobileAds

class GameViewController: UIViewController , GADInterstitialDelegate {


var interstitialAds : GADInterstitial!


override func viewDidLoad() {
    super.viewDidLoad()



    createAndLoadAd()
    NotificationCenter.default.addObserver(self, selector: #selector(GameViewController.showAds), name: NSNotification.Name("notification"), object: nil)


}


func createAndLoadAd(){
    let request = GADRequest()
    let interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
    request.testDevices = [kGADSimulatorID]
    interstitial.delegate = self
    interstitial.load(request)
    interstitialAds = interstitial
}

func showAds(){

    if interstitialAds.isReady {
        interstitialAds.present(fromRootViewController: self)
    }
}

func interstitialDidDismissScreen(_ ad: GADInterstitial) {
    createAndLoadAd()
}


override var shouldAutorotate: Bool {
    return true
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    if UIDevice.current.userInterfaceIdiom == .phone {
        return .allButUpsideDown
    } else {
        return .all
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Release any cached data, images, etc that aren't in use.
}

override var prefersStatusBarHidden: Bool {
    return true
}

override func viewWillLayoutSubviews() {

    super.viewWillLayoutSubviews()

    let menu = Menu()
    let skView = self.view as! SKView

    skView.ignoresSiblingOrder = true

    menu.size = view.bounds.size
    menu.scaleMode = SKSceneScaleMode.resizeFill
    skView.presentScene(menu)


}

}

GameScene.swift

    func gameOver(){

    NotificationCenter.default.post(name: NSNotification.Name("notification"), object: nil)

    //reset everything
    self.run(SKAction.playSoundFileNamed("Sound/die.wav", waitForCompletion: false))
    hud.updateScore(score: Int(score))


    player.die()
    hud.showScore()
    hud.showRestartMenu()



}   

HUD.swift

    import SpriteKit

    class HUD : SKNode {
    var scoreLabel = SKLabelNode(text: "0")
    let restartBut = SKSpriteNode()
    let menuBut = SKSpriteNode()
    let highScoreLabel = SKLabelNode()

    func createNode(screenSize : CGSize){

    scoreLabel.fontName = "AppleSDGothicNeo-SemiBold"
    scoreLabel.position = CGPoint(x: (screenSize.width / 2) - (screenSize.width / 4 * 2) , y: (screenSize.height / 2) - 50)
    scoreLabel.fontColor = UIColor.black
    scoreLabel.fontSize = 40
    scoreLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.center
    scoreLabel.verticalAlignmentMode = SKLabelVerticalAlignmentMode.center
    scoreLabel.zPosition = 50
    self.addChild(scoreLabel)

     //Restart and Menu button
    restartBut.texture = SKTexture(imageNamed: "restartButton")
    restartBut.name = "restartButton"
    restartBut.position = CGPoint(x: 0, y: 0)
    restartBut.zPosition = 50
    restartBut.size = CGSize(width: 400, height: 400)

    menuBut.texture = SKTexture(imageNamed: "menuButton")
    menuBut.name = "menuButton"
    menuBut.position = CGPoint(x: 0, y: -300)
    menuBut.zPosition = 50
    menuBut.size = CGSize(width: 150, height: 150)

    highScoreLabel.fontName = "AppleSDGothicNeo-SemiBold"
    highScoreLabel.position = CGPoint(x: 0, y: 450)
    highScoreLabel.fontColor = UIColor.black
    highScoreLabel.fontSize = 45
    highScoreLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.center
    highScoreLabel.verticalAlignmentMode = SKLabelVerticalAlignmentMode.center
    highScoreLabel.zPosition = 50
    }

    func showRestartMenu(){

    restartBut.alpha = 0
    menuBut.alpha = 0
    highScoreLabel.alpha = 0

    self.addChild(restartBut)
    self.addChild(menuBut)
    self.addChild(highScoreLabel)

    restartBut.run(SKAction.fadeAlpha(to: 1, duration: 0.35))
    menuBut.run(SKAction.fadeAlpha(to: 1, duration: 0.35))
    highScoreLabel.run(SKAction.fadeAlpha(to: 1, duration: 0.35))





    }

    func updateScore(score : Int){
    var highScore = UserDefaults().integer(forKey: "highScore")
    let number = NSNumber(value: score)
    let formatter = NumberFormatter()

    if let scoreText = formatter.string(from: number){
        scoreLabel.text = scoreText
    }




    if Int(score) > highScore {
        highScore = Int(score)
        highScoreLabel.text = NSString.init(format: "Highscore : %i", highScore) as String

        let highScoreDefs = UserDefaults.standard
        highScoreDefs.set(highScore, forKey: "highScore")
        highScoreDefs.synchronize()

    }

    highScoreLabel.text = "Highscore : \(highScore)"

}
Hung Teoh
  • 13
  • 6

1 Answers1

1

Go to your GameViewController and move all the code from ViewWillLayoutSubviews into ViewDidLoad. ViewDidLoad is only called once when the GameViewController loads. ViewWillLayoutSubviews on the other hand can be called multiple times, like when your ad is shown, which will than load your MenuScene again.

As a tip you should put your notification keys into an extension to avoid typos and be more specific with the names as a matter of good practice.

So add this above any class or in a new swift file

extension Notification.Name {
    static let showAd = Notification.Name("ShowAdNotification")
}

Than you can change your observers to this

NotificationCenter.default.addObserver(self, selector: #selector(showAds), name: .showAd, object: nil)

NotificationCenter.default.post(name: .showAd, object: nil)

You can also check out my helper on GitHub if you want to have a cleaner more reusable solution.

https://github.com/crashoverride777/SwiftyAds

I also noticed that you are using .resizeFill in your GameViewController scale mode. You should not do this, your game will look different on each device and it will be a nightmare to manage. You should use the default scaleMode .aspectFill which is usually the best setting.

You should also give the scene a fixed size and not size it depending on the bounds of the view (view.bounds.size).

How to make SKScene have fixed width?

How do I size sprites in a universal sprite kit game

Hope this helps

Community
  • 1
  • 1
crashoverride777
  • 10,581
  • 2
  • 32
  • 56
  • I have updated the code. When the player( game character) die, and the ads shows up and when I close the ad, the current scene disappear and instead it shows the Menu scene(which is the first scene after my app launches....*sry, not WelcomeScene by the way* ). I was expecting it to show me the restartButton which I added it into HUD and addchild to HUD when game is over. – Hung Teoh Apr 19 '17 at 16:10
  • I still dont see code that indicates that any scene transition is happening. Please show the transition code that takes you to GameOverScene – crashoverride777 Apr 19 '17 at 16:12
  • Also I just noticed you are using .ResizeFill in your GameViewController scale mode. You should not do this, your game will look different on each device and it will be a nightmare to manage. You should use the default scaleMode .aspectFill which is usually the best setting. – crashoverride777 Apr 19 '17 at 16:14
  • and not give the scene the size of the of the bounds (view.bounds.size). You should give it a fixed scene size. – crashoverride777 Apr 19 '17 at 16:15
  • http://stackoverflow.com/questions/42878452/how-to-make-skscene-have-fixed-width/42886511#42886511 – crashoverride777 Apr 19 '17 at 16:16
  • Thx ! I'm actually new to swift thx for the tips anyway. And about the transition actually there no GameOverScene, what I did is basically call the addchild to the HUD where i set my zposition to 50 when the player touches an enemy – Hung Teoh Apr 19 '17 at 18:29
  • You are welcome about the tips. Could you please update your question again with all the Hud code as well and or any other relevant code. I cannot grasp the full picture yet. – crashoverride777 Apr 19 '17 at 18:30
  • particularly the showScore and showRestartMenu methods – crashoverride777 Apr 19 '17 at 18:32
  • actually Im very doubtful about this line of code `interstitialAds.present(fromRootViewController: self)` what does this line of code actually mean, I understand that this line show the ad to the user but does it bring me to the first scene where it shows up when I open the app? – Hung Teoh Apr 20 '17 at 07:11
  • That line presents the ad from the rootViewController. I think I noticed your mistake. Try moving all the code from ViewWillLayoutSubviews into ViewDidLoad. ViewDidLoad is only called once when the GameViewController loads, whereas ViewWillLayoutSubviews is/can be called multiple times (like when your ad is shown). I updated my answer. – crashoverride777 Apr 20 '17 at 11:32
  • You are very welcome and thanks for marking. Happy coding. – crashoverride777 Apr 20 '17 at 12:46