I am trying to implement interstitial AdMob to my game app. But I have not had much luck so far. The code doesn't seem to have a bug but however it does not display the app. Any help would be much appreciate it. Thank you!
Here is my code:
import UIKit
import SpriteKit
import GoogleMobileAds
class GameViewController: UIViewController, GADInterstitialDelegate {
var interstitial: GADInterstitial!
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene(fileNamed:"GameScene") {
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* 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)
}
interstitial = GADInterstitial(adUnitID: "ca-app-pub-5713504307801022/7610056592")
let request = GADRequest()
interstitial.loadRequest(request)
func CreateAD() -> GADInterstitial {
let interstital = GADInterstitial(adUnitID: "ca-app-pub-5713504307801022/7610056592")
interstitial.loadRequest(GADRequest())
return interstital
}
if gameOver == true {
if (interstitial.isReady){
interstitial.presentFromRootViewController(self)
interstitial = CreateAD()
}
}
}
Related
Want to preload textureAtlases before game starts, so I decided to put scene starter code into completion handler, but for some reason app crashes. Here is my code:
import UIKit
import SpriteKit
import GameplayKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let gpuAtlas = SKTextureAtlas(named: "GP")
let ppAtlas = SKTextureAtlas(named: "PP")
SKTextureAtlas.preloadTextureAtlases([gpuAtlas, ppAtlas]) {
if let view = self.view as? SKView {
let scene = GameScene(size: self.view.bounds.size)
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
}
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
override var prefersStatusBarHidden: Bool {
return true
}
}
If I remove preload texture atlas method everything will work as usual, but I want preload textures to have a change to get rid of first keyframe freeze because of loading textures in cache.
Error:
fatal error: unexpectedly found nil while unwrapping an Optional value
Update:
It crashes on GameScene.swift file in method didSimulatePhysics.
What I do wrong guys?
Try this (use main thread for manipulation with view and weak self):
SKTextureAtlas.preloadTextureAtlases([gpuAtlas, ppAtlas]) { [weak self] in
guard let gameView = self?.view as? SKView else { return }
DispatchQueue.main.async {
let scene = GameScene(size: gameView.bounds.size)
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
gameView.presentScene(scene)
gameView.ignoresSiblingOrder = true
gameView.showsFPS = true
gameView.showsNodeCount = true
}
}
Did you check if scene is optional? If so:
guard let scene = GameScene(size: gameView.bounds.size) else { return }
This
let gpuAtlas = SKTextureAtlas(named: "GP")
let ppAtlas = SKTextureAtlas(named: "PP")
SKTextureAtlas.preloadTextureAtlases([GP, PP]) {}
should not compile - the variables are named gpuAtlas and ppAtlas and not GP and PP.
I am trying to program a button to set a UserDefault to true. And when the view loads I want it to check if the value of the user default is true. If it is I want it to follow through with a line of code.
Here is my code:
import UIKit
import SpriteKit
import AVFoundation
var bombSoundEffect: AVAudioPlayer!
let instruct = UserDefaults.standard
class GameViewController: UIViewController {
#IBOutlet weak var intructions: UIButton!
#IBAction func intructions(_ sender: AnyObject) {
instruct.set(true, forKey: "instructions")
}
override func viewDidLoad() {
super.viewDidLoad()
if instruct.value(forKey: "instructions") {
intructions.isHidden = true
}
let path = Bundle.main.path(forResource: "Untitled2.wav", ofType:nil)!
let url = URL(fileURLWithPath: path)
do {
let sound = try AVAudioPlayer(contentsOf: url)
bombSoundEffect = sound
sound.numberOfLoops = -1
sound.play()
} catch {
// couldn't load file :(
}
if let scene = GameScene(fileNamed:"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
scene.size = self.view.bounds.size
skView.presentScene(scene)
}
}
Change
if instruct.value(forKey: "instructions")
to
if instruct.bool(forKey: "instructions")
I'm following a tutorial to create a "tetris" game in Swift with XCode 7. I followed every single step in this tutorial, but I'm getting a runtime error:
Could not cast value of type 'SCNView' (0x106c19778) to 'SKView' (0x1068fcad0).
My GameViewController.swift is as follows:
import UIKit
import SceneKit
import SpriteKit
class GameViewController: UIViewController {
var scene: GameScene!
var swiftris:Swiftris!
override func viewDidLoad() {
super.viewDidLoad()
//Configure the view
let skView = view as! SKView
skView.multipleTouchEnabled = false
//Create and configure the scene
scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
scene.tick = didTick
swiftris = Swiftris()
swiftris.beginGame()
//Presente the scene.
skView.presentScene(scene)
scene.addPreviewShpaeToScene(swiftris.nextShape!){
self.swiftris.nextShape?.moveTo(StartingColumn, row: StartingRow)
self.scene.movePreviewShape(self.swiftris.nextShape!){
let nextShapes = self.swiftris.newShape()
self.scene.startTicking()
self.scene.addPreviewShpaeToScene(nextShapes.nextShape!) {}
}
}
}
override func prefersStatusBarHidden() -> Bool {
return true
}
func didTick(){
swiftris.fallingShape?.lowerShapeByOneRow()
scene.redrawShape(swiftris.fallingShape!, completion: {})
}
}
I already search for it on google and here and I didn`t find anything related to SCNView and SKView.
Thank you in advance.
I did find the problem with my code. I instantiate the SKView as the view inside GameViewController:
self.view = SKView()
let skView = view as! SKView
Before I do that, I tried to change the class of the view to SKView in the storyboard, but it was not possible.
I'd like to thank you for the revisions.
I created a new Xcode Game project. I stripped the default animations in the project and added a new Swift file and a new .sks both called MenuScene.
In my GameViewController, I replaced references to by GameScene with MenuScene as I want this scene to launch first:
override func viewDidLoad() {
super.viewDidLoad()
// Load 'GameScene.sks' as a GKScene. This provides gameplay related content
// including entities and graphs.
if let scene = GKScene(fileNamed: "MenuScene") {
// Get the SKScene from the loaded GKScene
if let sceneNode = scene.rootNode as! MenuScene? {
// Set the scale mode to scale to fit the window
sceneNode.scaleMode = .aspectFill
// Present the scene
if let view = self.view as! SKView? {
view.presentScene(sceneNode)
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
}
}
When I try to launch I get the following error:
Could not cast value of type 'SKScene' (0x1105624) to 'Spritekit10.MenuScene' (0x104c38).
If I change it back to GameScene, which appears to have the exact same setup, all seems fine.
Can anyone point me in the right direction with what the problem is with this?
On my MenuScene.sks under Custom Class, I've added MenuScene thinking that was the problem but the error still shows (and the textfield seems to randomly clear itself when I go back to it.
import SpriteKit
import GameplayKit
class GameScene: SKScene {
override func sceneDidLoad() {
}
}
.
import SpriteKit
import GameplayKit
class MenuScene: SKScene {
override func sceneDidLoad() {
}
}
So I figured out the issue.
For the .sks file, I had to add a name to the scene in the attributes inspector (even though it was blank in the GameScene). Once I done this, the custom class value saved and the file now loads without an error. Not sure if thats a bug or by design.
Your problem is you are trying to upcast an SKScene to a MenuScene.
This cannot be done, I see you have checked your custom class in your sks file to ensure that it is set to MenuScene, but did you make sure you saved it correctly? You need to type it in and hit enter, if you do not, then the scene will not auto save it, and when you leave will clear it out.
For Xcode 8.0/8.1 , create a swift file named "Menuscene" and an sks file named "Menuscene" too.
delete everything in the Menuscene swift file and insert this code
import SpriteKit
import GameplayKit
class Menuscene: SKScene {
override func didMove(to view: SKView) {
let menutext = SKLabelNode()
menutext.text = "MEnuscene"
menutext.position = CGPoint(x: 0, y: 0)
menutext.fontSize = 120
self.backgroundColor = UIColor.blue
addChild(menutext)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let gamescene = SKScene(fileNamed: "GameScene")
gamescene?.scaleMode = .fill
self.scene?.view?.presentScene(gamescene!,transition: SKTransition.doorsCloseHorizontal(withDuration: 1.0))
}
override func update(_ currentTime: TimeInterval) {
}
}
and in the attribute inspector tab, set name to "Menuscene", hit enter (very important). then on the next tab, set custom class name to "Menuscene",hit enter (very important).
In your Gamescene.swift file, double-check to be sure your class starts with
class GameScene: SKScene {
add this code to your touchesBegan func
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let Menuscene = SKScene(fileNamed: "Menuscene")
Menuscene?.scaleMode = .fill
self.scene?.view?.presentScene(Menuscene!,transition: SKTransition.doorsOpenVertical(withDuration: 1.0))
}
finally in your Gameviewcontroller file, delete everything and insert this code
import UIKit
import SpriteKit
import GameplayKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
if let scene = SKScene(fileNamed: "Menuscene") {
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
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
}
}
you're welcome! you should be able to tap from game screen to menu screen.
I found something weird.
My project name has a "-" character.
After I removed this character from Target name, the project could cast scene.rootNode to GameScene.
It works on iOS 10.3.1 for me.
override func viewDidLoad() {
super.viewDidLoad()
let fileName = "GameScene"
// Load 'GameScene.sks' as a GKScene. This provides gameplay related content
// including entities and graphs.
guard let scene = GKScene(fileNamed: fileName) else {
return
}
guard let sceneNode = scene.rootNode as? GameScene ?? GameScene(fileNamed: fileName) else {
return
}
// Copy gameplay related content over to the scene
sceneNode.entities = scene.entities
sceneNode.graphs = scene.graphs
// Set the scale mode to scale to fit the window
sceneNode.scaleMode = .aspectFill
// Present the scene
if let view = self.view as! SKView? {
view.presentScene(sceneNode)
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
I have been trying to display adds when the game is over for my game app. I have created a game over variable on GameScene.swift and I call that variable in the GameViewController.swift. However, the add is displayed shortly after the game starts. Could anyone point out what am I doing wrong? Here is my code:
import UIKit
import SpriteKit
import GoogleMobileAds
private var interstitial: GADInterstitial?
class GameViewController: UIViewController, GADInterstitialDelegate {
private var interstitial: GADInterstitial?
override func viewDidLoad() {
super.viewDidLoad()
interstitial = createInterstitial()
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
if let scene = GameScene(fileNamed:"GameScene") {
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* 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)
}
}
override func prefersStatusBarHidden() -> Bool {
return true
}
private func createInterstitial() -> GADInterstitial {
let interstitial = GADInterstitial(adUnitID: "ca-app-pub-5713504307801022/7610056592")
interstitial.delegate = self
let request = GADRequest()
request.testDevices = ["ca-app-pub-5713504307801022/7610056592"]
interstitial.loadRequest(request)
return interstitial
}
func interstitialDidDismissScreen(ad: GADInterstitial!) {
interstitial = createInterstitial()
}
func interstitialDidReceiveAd(ad: GADInterstitial!) {
if (interstitial!.isReady) {
if gameOver1 == true {
self.interstitial!.presentFromRootViewController(self)
interstitial = createInterstitial()
}
}
}
}
First - this is how you should load and recycle AdMob interstitials -https://stackoverflow.com/a/37938286/2405378
Second - viewWillLayoutSubviews can be called multiple times and each time this method creates new instance of the GameScene - with gameOver1 being false?