问题
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 NotificationCenter
but 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)"
}
回答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
来源:https://stackoverflow.com/questions/43490200/after-showing-interstitial-ad-when-gameover-scene-return-to-welcomescene