I feel like I've looked everywhere and I can't figure it out. I'm trying to show a banner ad at the bottom of my menu screen like so:
But after I display my "game over" screen (which also has an ad on it) The main menu looks like this:
Any help would be greatly appreciated. I call the ads by using the NSNotificationCenter and the GameOver SKScene calls presentScene to get back to the Main Menu. I assume it has something to do with frame size in that call, but I do not know how to fix it.
Inside my GameViewController:
override func viewDidLoad() {
//code
loadAds()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "showiAdBanner", name: "showiAdBanner", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "hideiAdBanner", name: "hideiAdBanner", object: nil)
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
adBannerView.hidden = false
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
adBannerView.hidden = true
}
func loadAds(){
adBannerView = ADBannerView(frame: CGRect.zeroRect)
adBannerView.center = CGPoint(x: adBannerView.center.x, y: view.bounds.size.height - adBannerView.frame.size.height / 2)
adBannerView.delegate = self
adBannerView.hidden = true
adBannerView.layer.zPosition = 10
view.addSubview(adBannerView)
}
func showiAdBanner() {
if adBannerView.bannerLoaded {
adBannerView.hidden = false
}
}
func hideiAdBanner() {
adBannerView.hidden = true
}
Inside SpriteKit "Start" Scene:
override func didMoveToView(view: SKView) {
//code
NSNotificationCenter.defaultCenter().postNotificationName("showiAdBanner", object: nil)
}
I ended up figuring out a solution for my situation. I simply have a different SKScene load up, wait a second, then calls my other one. This way, the menu always looks the same.
Related
How do I show an interstitial ad from admob every x times the user has died or every x times the user does something like presses a button? This is how I showed an interstitial ad on my GameScene and limited ad impressions with a simple if statement.
This will only work if you have the GoogleMobileAds.sdk and have imported the googlemobileads module into your GameViewController, and GameScene, OR GameOverScene.
I'll be showing you cross-scene ad implementation and programmatically limiting ad impressions.
First, in your GameViewController:
import GoogleMobileAds
class GameViewController: UIViewController, GADInterstitialDelegate {
var myAd = GADInterstitial()
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(GameViewController.loadAndShow), name: "loadAndShow", object: nil)
}
Create two functions at the bottom of your GameViewController:
func loadAndShow() {
myAd = GADInterstitial()
let request = GADRequest()
myAd.setAdUnitID("ca-app-pub-3940256099942544/4411468910")
myAd.delegate = self
myAd.loadRequest(request)
}
func interstitialDidReceiveAd(ad: GADInterstitial!) {
if (self.myAd.isReady) {
myAd.presentFromRootViewController(self)
}
}
You are done with GameViewController. Now head to GameOverScene or GameScene, whatever you need.
Create a global int variable:
var playCount = Int()
In your DidMoveToView say:
playCount = 1
This part is sort of confusing, kinda, not really. Go to your touchesBegan and find where you add actions to a button if it's pressed. For example, a resetGame button resets the scene. Add this there and increment the playButton Int like so:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches{
let location = touch.locationInNode(self)
if resetGame.containsPoint(location) {
restartScene()
playCount += 1
}
Last step. Add these two functions to the bottom of the scene you want to show interstitial ads in:
func displayAd() {
NSNotificationCenter.defaultCenter().postNotificationName("loadAndShow", object: nil)
}
func checkAd() {
if playCount % 4 == 0 {
displayAd()
}
}
}
Now every fourth time that the user presses the reset game button or dies, an interstitial ad should show up. I hope this helps.
EDIT: I forgot to tell you to call the checkAd() function. Call this function wherever your players dies. So if you have a Bool variable called died or gameover call it in the same spot. For example..
if died == true {
checkAd()
}
import UIKit
import SpriteKit
import GoogleMobileAds
var playCount = Int()
class GameViewController: UIViewController, GADBannerViewDelegate {
#IBOutlet var banner: GADBannerView!
var myAd = GADInterstitial()
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(GameViewController.loadAndShow), name: "loadAndShow", object: nil)
let scene = MainScene(size: CGSize(width: 1536, height: 2048))
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = false
skView.showsNodeCount = false
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
skView.presentScene(scene)
banner.hidden = true
banner.delegate = self
banner.adUnitID = "ca-app-pub-8889875503423788/7902691359"
banner.rootViewController = self
banner.loadRequest(GADRequest())
}
func loadAndShow() {
myAd = GADInterstitial()
let request = GADRequest()
myAd.setAdUnitID("ca-app-pub-8889875503423788/7902691359")
myAd.delegate = self
myAd.loadRequest(request)
}
func interstitialDidReceiveAd(ad: GADInterstitial!) {
if (self.myAd.isReady) {
myAd.presentFromRootViewController(self)
}
}
func adViewDidReceiveAd(bannerView: GADBannerView!) {
banner.hidden = false
}
func adView(bannerView: GADBannerView!, didFailToReceiveAdWithError error: GADRequestError!) {
banner.hidden = true
}
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return .AllButUpsideDown
} else {
return .All
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
I'm using Swift and SpriteKit, and everything is made inside my GameViewController and GameScene.
This is all code concerning the ads inside my GameViewController:
class GameViewController: UIViewController, ADBannerViewDelegate, GADBannerViewDelegate {
var adBannerView: ADBannerView!
var gadBannerView: GADBannerView!
var bannerDisplayed = false
var bannerNow = "iAd"
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = false
skView.showsNodeCount = false
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
if((UIDevice.currentDevice().userInterfaceIdiom == .Phone) && (UIScreen.mainScreen().bounds.height <= 480)) {
println("<= iPhone 4S")
scene.size.height = skView.bounds.size.height * 2
scene.size.width = skView.bounds.size.width * 2
}
NSNotificationCenter.defaultCenter().addObserver(self, selector: "hideADBanner", name: "hideAd", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "showADBanner", name: "showAd", object: nil)
self.adBannerView = self.loadAds()
skView.presentScene(scene)
println(gadBannerView)
}
}
func loadAds()->ADBannerView{
var adBannerView2 = ADBannerView(frame: CGRect.zeroRect)
adBannerView2.center = CGPoint(x: adBannerView2.center.x, y: view!.bounds.size.height - adBannerView2.frame.size.height / 2)
adBannerView2.delegate = self
adBannerView2.hidden = true
bannerNow = "iAd"
self.view?.addSubview(adBannerView2)
return adBannerView2
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
println("left for ad")
return true
}
func bannerViewActionDidFinish(banner: ADBannerView!) {
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
println("ad did load.")
println("Delegate: \(adBannerView.delegate)")
adBannerView.hidden = false
//gadBannerView?.removeFromSuperview()
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
//adBannerView.removeFromSuperview()
//self.gadBannerView = self.createGADBanner()
}
func createGADBanner()->GADBannerView {
var ad = GADBannerView()
ad = GADBannerView(frame: CGRectMake(0, 0, self.view.frame.size.width, 50))
ad.delegate = self
ad.rootViewController = self
ad.adUnitID = "xxxxxxxxxxx"
bannerNow = "GAD"
var reqAd = GADRequest()
//reqAd.testDevices = [GAD_SIMULATOR_ID] // If you want test ad's
ad.loadRequest(reqAd)
self.view.addSubview(ad)
println(ad)
return ad
}
func adViewDidReceiveAd(view: GADBannerView!) {
println("adViewDidReceiveAd:\(view)");
bannerDisplayed = true
relayoutViews()
}
func adView(bannerView: GADBannerView!, didFailToReceiveAdWithError error: GADRequestError!) {
gadBannerView.removeFromSuperview()
}
func relayoutViews() {
if (bannerDisplayed) {
var bannerFrame = gadBannerView!.frame
bannerFrame.origin.x = 0
bannerFrame.origin.y = self.view.bounds.size.height - bannerFrame.size.height
gadBannerView!.frame = bannerFrame
}
}
func hideADBanner() {
println(self.gadBannerView)
println(bannerNow)
//adBannerView?.hidden = true
//gadBannerView?.hidden = true
adBannerView?.removeFromSuperview()
gadBannerView?.removeFromSuperview()
}
func showADBanner() {
self.adBannerView = self.loadAds()
//adBannerView?.hidden = false
//gadBannerView?.hidden = false
}
So my plan is to get ads from AdMob when iAd is not working, but the problem is that my iAd "always works", even though I've changed the fill-rate inside the Developer tools in my iPhone.
When iAd loads the ad it works fine, the function bannerViewDidLoadAd() is called and the ad is displayed. Although sometimes when I load iAd it says that I've entered bannerViewDidLoadAd() but it only displays a white "box" with the iAd logo in the bottom. Now, this is not what I want because then AdMob is never gonna show. The println always put out the same delegate so it seems like that works at least.
This view never refreshes because everything, as I said, is handled in the GameScene where it's just removing and adding nodes.
Thank you!
You're over complicating things immensely with bool's, unnecessary functions, and it looks like you've actually created two ADBannerViews once in Interface Builder, self.adBannerView, and once programmatically, var adBannerView: ADBannerView!.
I've created an example with comments to help you along the way. Whats happening here is we are creating an ADBannerView, setting it up once in our viewDidLoad, and then hiding/showing our ADBannerView depending on if it receives an ad from the iAd network or not. I've left out the AdMob implementation as it should be pretty straight forward now.
import UIKit
import iAd // Import iAd
class ViewController: UIViewController, ADBannerViewDelegate { // Include the delegate for our ADBannerView
var adBannerView = ADBannerView() // Create our ADBannerView
// Create your GADBannerView here
override func viewDidLoad() {
super.viewDidLoad()
loadAds()
}
func loadAds() {
// Setup our ADBannerView
adBannerView = ADBannerView(frame: CGRect.zeroRect)
adBannerView.center = CGPoint(x: view.bounds.size.width / 2, y: view.bounds.size.height - adBannerView.frame.size.height / 2)
adBannerView.delegate = self
adBannerView.hidden = true
view.addSubview(adBannerView)
// Setup your GADBannerView here in the same manner
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
println("bannerViewDidLoadAd")
// We received an ad from iAd. Lets show our banner
adBannerView.hidden = false
// Hide your GADBannerView here
}
func bannerViewActionDidFinish(banner: ADBannerView!) {
println("bannerViewActionDidFinish")
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
println("didFailToReceiveAdWithError: \(error)")
// We failed to receive an ad from iAd. Lets hide our banner and print the error
adBannerView.hidden = true
// Show your GADBannerView here
}
when I run the game a white box appears at the top of the game which I'm guessing the ads are suppose to appear in there, but no ads ever appear!
Am I doing something wrong, missing a certain piece of code somewhere, or blind? haha.
I'm quite new to this iAd and everything!
Here is an image of it
Here is the ViewController Code!
import UIKit
import SpriteKit
import iAd
class GameViewController: UIViewController, ADBannerViewDelegate{
#IBOutlet var Banner: ADBannerView!
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
// Configure the view.
let skView = self.view as SKView
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
skView.presentScene(scene)
loadAds()
}
}
func loadAds() {
self.canDisplayBannerAds = true
Banner = ADBannerView(frame: CGRect.zeroRect)
Banner.center = CGPointMake(Banner.center.x, view.bounds.size.height - Banner.frame.size.height / 2)
Banner.delegate = self
Banner.hidden = true
view.addSubview(Banner)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
self.Banner.hidden = true
}
func bannerViewWillLoadAd(banner: ADBannerView!) {
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
return willLeave
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
self.Banner.hidden = false
}
Your issue is that you are using self.canDisplayBannerAds = true in addition to creating an ADBannerView programmatically. Remove self.canDisplayBannerAds = true from your loadAds function.
It seems to be working all of the sudden! Was getting error message, but it has gone away and the Ad has actually loaded! :)
Don't know what was going on!
I have the following code to pause game scene:
class GameProcessScene: SKScene {
...
var onPause: Bool = false {
willSet {
self.paused = newValue
self.view?.paused = newValue
}
}
...
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
for touch in touches {
let location = touch.locationInNode(self)
let possiblePauseNode = self.nodeAtPoint(location)
if (possiblePauseNode.name == "pauseButton") {
if (self.paused) {
onPause = false
} else {
onPause = true
}
return
}
...
}
}
It works to pause by pressing button. But i also want to pause game when it appears from background. I am trying to do this from ViewController class:
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "pauseGameScene", name: UIApplicationWillEnterForegroundNotification, object: nil)
}
func pauseGameScene() {
let view = self.view as SKView
let scene = view.scene
switch scene {
case is MainMenuScene:
println("MainMenu")
case let game as GameProcessScene:
game.onPause = true
default:
println("default")
}
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
But it doesnt work when game appears from background.
Can anybody help? Thanks!
UPD1: Also tried UIApplicationWillResignActiveNotification, UIApplicationDidEnterBackgroundNotification but game.onPause = true still doesnt work. It changes "SKScene.paused" property to true, but the actions are still executing when game enters foreground, even game scene was paused before it goes background.
UPD2: I moved observers and selectors from ViewController class to GameProcessScene: SKScene class - same effect, "paused" property changes, but in fact gameplay is continuing.
I solved my problem by creating a property called isPaused and overriding the paused property to always follow the isPaused property. Note : This disables the SKSCene from automatically pausing when going to background mode. You have to manually set the isPaused property. So only use it in scenes where you actually need the pause mode on resume.
class GameScene: SKScene,SKPhysicsContactDelegate {
// Initializers
var isPaused : Bool = false {
didSet {
self.paused = isPaused
}
}
override var paused : Bool {
get {
return isPaused
}
set {
super.paused = isPaused
}
}
}
In ViewController
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "pauseGameScene", name: UIApplicationWillResignActiveNotification, object: nil)
}
func pauseGameScene() {
println("will become inactive")
let view = self.view as SKView
let scene = view.scene
switch scene {
case let game as GameScene:
game.isPaused = true
default:
println("default")
}
}
Did you try put your code into
override func viewWillAppear(animated: Bool) {
//Put your pauseGameScene(); code here
}
This method called before your view appears every times. The viewDidLoad() run only once after your instance is initialized.
I made simple game with Swift and SpriteKit. Everything seems to work but I have a problem with my iAd Setup. I only want to show the ad banner in specific scenes (main menu and game over) not during the gameplay.
My iAd setup works but only if it is displayed all the time.
My last attempt to fix it was with the NSNotificationCenter method. I have done it as I have seen it in other question/answers here but the app crashes immediately after launch.
Hope that someone could help me. Just let me know if you need more of my code.
Thanks in advance.
GameViewController.swift
class GameViewController: UIViewController, ADBannerViewDelegate {
var adBannerView = ADBannerView(frame: CGRect.zeroRect)
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleNotification", name: "hideAd", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleNotification", name: "showAd", object: nil)
self.adBannerView.delegate = self
self.adBannerView.hidden = true
adBannerView.center = CGPoint(x: adBannerView.center.x, y: view.bounds.size.height - adBannerView.frame.size.height / 2)
view.addSubview(adBannerView)
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
// Configure the view.
let skView = self.view as SKView
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
var scene: SKScene = MainMenu(size: skView.bounds.size)
scene.scaleMode = SKSceneScaleMode.AspectFill
skView.presentScene(scene)
}
}
func handleNotification(notification: NSNotification){
if notification.name == "hideAd"{
adBannerView.hidden = true
}else if notification.name == "showAd"{
adBannerView.hidden = false
}
}
//iAD Setup
func bannerViewWillLoadAd(banner: ADBannerView!) {
println("Ad loads")
}
func bannerViewDidLoadAd(banner: ADBannerView!){
println("Ad loaded")
self.adBannerView.hidden = false
}
func bannerViewActionDidFinish(banner: ADBannerView!) {
println("resume scene")
let skView = self.view as SKView
skView.paused = false
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
println("pause scene")
let skView = self.view as SKView
skView.paused = true
return true
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
println("Failed to load ad")
self.adBannerView.hidden = true
} more code....
MainMenu.swift
class MainMenu: SKScene{
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(size:CGSize){
super.init(size: size)
NSNotificationCenter.defaultCenter().postNotificationName("showAd", object: nil)
more code...
This works for me
In my view controller I have this code:
// Banner Ad
var SH = UIScreen.mainScreen().bounds.height
let transition = SKTransition.fadeWithDuration(1)
var UIiAd: ADBannerView = ADBannerView()
override func viewWillAppear(animated: Bool) {
var BV = UIiAd.bounds.height
UIiAd.delegate = self
UIiAd.frame = CGRectMake(0, SH + BV, 0, 0)
self.view.addSubview(UIiAd)
}
override func viewWillDisappear(animated: Bool) {
UIiAd.delegate = nil
UIiAd.removeFromSuperview()
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
var BV = UIiAd.bounds.height
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1) // Time it takes the animation to complete
UIiAd.alpha = 1 // Fade in the animation
UIView.commitAnimations()
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1)
UIiAd.alpha = 0
UIView.commitAnimations()
}
func showBannerAd() {
UIiAd.hidden = false
var BV = UIiAd.bounds.height
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1) // Time it takes the animation to complete
UIiAd.frame = CGRectMake(0, SH - BV, 0, 0) // End position of the animation
UIView.commitAnimations()
}
func hideBannerAd() {
UIiAd.hidden = true
var BV = UIiAd.bounds.height
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1) // Time it takes the animation to complete
UIiAd.frame = CGRectMake(0, SH + BV, 0, 0) // End position of the animation
UIView.commitAnimations()
}
override func viewDidLoad() {
super.viewDidLoad()
self.UIiAd.hidden = true
self.UIiAd.alpha = 0
NSNotificationCenter.defaultCenter().addObserver(self, selector: "hideBannerAd", name: "hideadsID", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "showBannerAd", name: "showadsID", object: nil)
let scene = GameScene()
// Configure the view.
let skView = self.view as SKView
skView.showsFPS = false
skView.showsNodeCount = false
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFit
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
scene.size = skView.bounds.size
skView.presentScene(scene, transition: transition)
}
To display it in the scene I want (for me it's the GameOver scene) I did this:
override func didMoveToView(view: SKView) {
showAds()
// Rest of your code here...
}
func showAds(){
NSNotificationCenter.defaultCenter().postNotificationName("showadsID", object: nil)
}
Basically this code creates a banner off the scene, and when the banner is loaded and the scene gets called, it slides up from the bottom. When you switch scenes, it offsets it again and when you come back to that scene, it slides up from the bottom again. If the banner doesn't load, it's off screen so no worries about it showing a white bar. Also, it sets the alpha to 0 if it doesn't load just in case (makes it invisible). Hope this helps.
I USE THIS TO PRESENT THE iAd Banner in subview
var vc = self.view?.window?.rootViewController
vc?.view.addSubview(adView!)
When I want to hide it when in the game (because iAd reduce FPS) I call
adView!.removeFromSuperview()
When the user finished the Game just add
var vc = self.view?.window?.rootViewController
vc?.view.addSubview(adView!)
to show the iAd banner again
BUT YOU NEED TO IMPLEMENT THIS CODE IN GameViewController
class GameViewController: ADBannerViewDelegate (you needed this too)
also don't forget to import iAd at the top of gameviewcontroller
also import iAd framework to the project
override func viewDidLoad() {
self.ShowAd()
//Have this in view didLoad too
func ShowAd() {
super.viewDidLoad()
adView = ADBannerView(adType: ADAdType.Banner)
adView!.delegate = self
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
self.view.addSubview(adView!)
self.view.layoutIfNeeded()
println("Pass")
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
adView!.removeFromSuperview()
/*var alert = UIAlertController(title: "iAd Message", message:
"iAd Fail To Load", preferredStyle: UIAlertControllerStyle.Alert)
self.presentViewController(alert, animated: false, completion: nil)
alert.addAction(UIAlertAction(title: "dismiss", style: UIAlertActionStyle.Default,
handler: nil))
self.view.layoutIfNeeded()*/
println("fail")
}