Admob Interstitials In SpriteKit - Swift 3 - swift

This question has been asked before but this was quite a while ago and not updated for swift 3 or spritekit.
In my game, once you die, a gameover scene occurs. I would like to be able to present an interstitial ad every 3 times the restart/home button is pressed. Sorry, I am a real beginner and the admob documentation is no help either.
My code for my gameover scene:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self);
if atPoint(location) == homeButton {
let homeScene = GameScene(size: self.size)
let skView = self.view as SKView!
let myTransition = SKTransition.fade(withDuration: 1)
skView?.ignoresSiblingOrder = true
homeScene.scaleMode = .resizeFill
homeScene.size = (skView?.bounds.size)!
skView?.presentScene(homeScene, transition: myTransition)
}
if atPoint(location) == restartButton {
let restartScene = PlayScene(size: self.size)
let skView = self.view as SKView!
let myTransition = SKTransition.fade(withDuration: 1)
skView?.ignoresSiblingOrder = true
restartScene.scaleMode = .resizeFill
restartScene.size = (skView?.bounds.size)!
skView?.presentScene(restartScene, transition: myTransition)
}}

I just started using this library for my own app called SwiftyAds to help integrate with AdMob.
There is one method in particular that will help you, it is this: SwiftyAds.shared.showInterstitial(withInterval: 3, from: view?.window?.rootViewController)
You would put that code where you are detecting the home or restart button. Every 3rd time it is called, the interstitial will show.

Related

AVAudioPlayer causing SpriteNodes to jerk when animating

I am working on app atm where the user sees nodes animating across the screen. When the node passes a certain target area, the user must press a button and then a avplayer sound will play.
The problem is, anytime the user presses the button and the sound plays, the nodes all jerk and I have no idea why. To replicate the problem I am having, here is an example project I put together in few mins.
import SpriteKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let skView = self.view as! SKView
let scene = GameScene(size: CGSizeMake(self.view.frame.size.width, self.view.frame.size.height))
skView.presentScene(scene)
}
}
import SpriteKit
import AVFoundation
class GameScene: SKScene {
var buttonNode : SKSpriteNode?
override init(size: CGSize)
{
super.init(size: size)
self.backgroundColor = SKColor.whiteColor()
self.view?.backgroundColor = UIColor.whiteColor()
}
override func didMoveToView(view: SKView)
{
buttonNode = SKSpriteNode(imageNamed: "button")
buttonNode?.name = "button"
buttonNode?.position = CGPointMake(200, 200)
buttonNode?.size = CGSizeMake(150, 150)
self.addChild(buttonNode!)
NSTimer.scheduledTimerWithTimeInterval(1.5, target: self, selector: #selector(self.animateNodes), userInfo: nil, repeats: true)
}
var avPlayer : AVAudioPlayer?
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
for touch in touches
{
let viewTouchLocation = touch.locationInView(self.view)
let sceneTouchPoint = self.convertPointFromView(viewTouchLocation)
let touchedNode = self.nodeAtPoint(sceneTouchPoint)
if(touchedNode.name == "button")
{
let avURL = NSURL.fileURLWithPath(NSBundle.mainBundle().pathForResource("exampleSound", ofType: "wav")!)
avPlayer = try? AVAudioPlayer(contentsOfURL: avURL)
avPlayer?.volume = 0.2
avPlayer?.play()
}
}
}
func animateNodes()
{
let sprite = SKSpriteNode(imageNamed: "shortMetalWhite")
sprite.color = UIColor.blackColor()
sprite.colorBlendFactor = 1.0
sprite.position = CGPointMake(self.view!.frame.size.width, 400)
self.addChild(sprite)
let noteDuration = 4.0
let actionMove = SKAction.moveTo(CGPointMake(-5, 400), duration: noteDuration)
let actionMoveDone = SKAction.removeFromParent()
sprite.runAction(SKAction.sequence([actionMove, actionMoveDone]))
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Does anyone have any idea what causes this? Is there something wrong with sprite nodes and avplayer that causes this? I have replicated this same code in a non game app, where you have a series of UIViews animating across the screen and a sound plays everytime you press a button and there is no issue with any lag or jerkiness. So what is it about sprite nodes and AVPlayer that causes this issue?
(Btw the issue is not as noticeable on the simulator, but when you run it on any iPhone or iPad, it is very noticeable)
Any help would be much appreciated
Edit:
If I swap to using AudioServices instead like this
if let soundURL = NSBundle.mainBundle().URLForResource("OHH10 Drums1DOTcom", withExtension: "wav") {
var mySound: SystemSoundID = 0
AudioServicesCreateSystemSoundID(soundURL, &mySound)
// Play
AudioServicesPlaySystemSound(mySound);
}
there is no lag, but then I have no control over the volume. So not an ideal solution
After doing more research, it seems its an issue with AVAudioPlayer, it is not really suited for playing repeating sounds effects in short succession.
So instead I swapped to using
SKAction.playSoundFileNamed("example.wav", waitForCompletion: false)
Again issue with this is that it does not allow you to control the volume. This means I had to open up audacity and modify the volume of each sound file to get it just right.
I would have preferred a better solution, but sadly this is the best I can find if I want to avoid any game lag

How can I put a mute button for background music in my Sprite Kit Game with Swift 2(Xcode 7)?

I am making a game with Sprite kit, I recently added background music to the game and it works, but i want to put a mute button that can allow the player to stop and play the background music while the game is running in case he don't like it. Thanks.
import AVFoundation
class GameScene: SKScene, SKPhysicsContactDelegate {
var backgroundMusic = SKAudioNode()
func restartScene(){
self.removeAllChildren()
self.removeAllActions()
died = false
gameStarted = false
score = 0
createScene()
}
func createScene(){
backgroundMusic = SKAudioNode(fileNamed: "Musicnamefile.mp3")
addChild(backgroundMusic)
}
override func didMoveToView(view: SKView) {
/* Setup your scene here */
createScene()
}
To create a button add this in didMoveToView:
// pause button
let pauseButton = SKLabelNode()
let pauseContainer = SKSpriteNode()
pauseContainer.position = CGPointMake(hud.size.width/1.5, 1)
pauseContainer.size = CGSizeMake(hud.size.height*3, hud.size.height*2)
pauseContainer.name = "PauseButtonContainer" // pause button
let pauseButton = SKLabelNode()
let pauseContainer = SKSpriteNode()
pauseContainer.position = CGPointMake(hud.size.width/1.5, 1)
pauseContainer.size = CGSizeMake(hud.size.height*3, hud.size.height*2)
pauseContainer.name = "PauseButtonContainer"
hud.addChild(pauseContainer)
pauseButton.position = CGPointMake(hud.size.width/2, 1)
pauseButton.text="I I"
pauseButton.fontSize=hud.size.height
//pauseButton.fontColor = UIColor.blackColor()
pauseButton.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Center
pauseButton.name="PauseButton"
hud.addChild(pauseButton)
I'm using the SKLabel to show the pause symbol and a container to increase the touch area. HUD is an rectangle of type SKNode at the top of my game. You have to add the nodes to an element in your game and change the size and position.
To react on the touch:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
let node = self.nodeAtPoint(location)
if (node.name == "PauseButton" || node.name == "PauseButtonContainer") {
Insert your code here ....
}
}
}

View distorted after connecting two scenes

I have the following problem:
In my game, I have two scenes (GameScene.swift and GameOverScene.swift). I think they are pretty self-explanatory, in GameScene.swift happens everything connected to the game and if the player collides with the enemy, he will be sent to GameOverScene.swift. This is the code:
var transition:SKTransition = SKTransition.flipHorizontalWithDuration(0.5)
var gameOverScene:SKScene = GameOverScene(size: self.size, dead: true)
self.view?.presentScene(gameOverScene, transition: transition)
As soon as the player touches the screen, he should be redirected to the GameScene:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
var transition:SKTransition = SKTransition.flipHorizontalWithDuration(0.5)
var scene:SKScene = GameScene(size: self.size)
self.view?.presentScene(scene, transition: transition)
}
}
Unfortunately, everything in the GameOverScene.swift is completely distorted and the background color changes (?!). When going back to GameScene.swift, it's distorted as well. This is how GameOverScene.swift is initialized:
class GameOverScene: SKScene {
init(size:CGSize, dead:Bool) {
super.init(size: size)
Any idea why this doesn't work properly? Thanks in advance!

How to seamlessly transition into Interstitial iAd in Swift?

So my code for showing an interstitial iAd works, but it is slow to load the Ads. When the user is at my GameOver scene and they hit retry, it does a random number check and if the number matches the one I said, it uses an NSNotificationCenter to load my interstitial iAd.
func interstitialAdChecker(){
var randomAd = Int(arc4random() % 3)
println(randomAd)
if randomAd == 1 {
NSNotificationCenter.defaultCenter().postNotificationName("showInterstitialAdsID", object: nil)
}
}
And in my game over scene, when the user taps replay, this is the code for transitioning scenes:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if self.nodeAtPoint(location) == self.replayButton {
gameOverLogo.removeFromParent()
replayButton.removeFromParent()
yourScore.removeFromParent()
highScore.removeFromParent()
rateButton.removeFromParent()
scoreBackground.removeFromParent()
interstitialAdChecker()
var scene = InstructionScene(size: self.size)
let skView = view as SKView!
skView.ignoresSiblingOrder = true
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
scene.scaleMode = .ResizeFill
scene.size = skView.bounds.size
skView.presentScene(scene, transition: transition)
}
}
}
There is a 1 - 3 second delay between when the InstructionScene loads and when the Interstitial iAd is shown, so does anyone know how to make it seamlessly slide up from the bottom AS SOON as the user hits retry? The 1 - 3 second delay means the user might start the game and have an ad pop up mid gameplay which is no good. Thanks!
Are you using the simulator or an actual device to test on? If you are using the simulator there can be a delay in showing ads from my experience.
If you are testing on your device then you should try delay your scene transition until the insterstitialAd has been handled by the user. You could set a bool for when the ad is showing so you don't transition. Then when the user cancels the ad the transition takes place.

How to transition scenes in Swift

In Objective-C, using Sprite-Kit, I would successfully use something like the following code in Objective-C to bring up a new scene
if ([touchedNode.name isEqual: #"Game Button"]) {
SKTransition *reveal = [SKTransition revealWithDirection:SKTransitionDirectionDown duration:1.0];
GameScene *newGameScene = [[GameScene alloc] initWithSize: self.size];
// Optionally, insert code to configure the new scene.
newGameScene.scaleMode = SKSceneScaleModeAspectFill;
[self.scene.view presentScene: newGameScene transition: reveal];
}
In trying to port my simple game to Swift, so far I have this working...
for touch: AnyObject in touches {
let touchedNode = nodeAtPoint(touch.locationInNode(self))
println("Node touched: " + touchedNode.name);
let touchedNodeName:String = touchedNode.name
switch touchedNodeName {
case "Game Button":
println("Put code here to launch the game scene")
default:
println("No routine established for this")
}
But I do not know what code to write to actually transition to another scene.
Question(s):
Can someone please provide an example of using SKTransition with Swift?
Would you normally create another "file" to put the other scene code in for the other scene, assuming you would have under Objective-C, or is there something about using Swift that means I should approach it differently?
Thank you
To start with your second question, it's kind of up to you. If you wish to, you can continue to follow the Objective-C convention of having one class per file, although this isn't a requirement, and wasn't in Objective-C either. That being said, if you have a couple of classes that are tightly related, but aren't made up of much code, it wouldn't be unreasonable to have them grouped in a single file. Just do what feels right, and don't make a huge blob of code in a single file.
Then for your first questions... Yes, you had a good deal of it already. Basically, from where you got up to, you need to create the instance of GameScene through its size: initializer. From there, you just set the properties and call present.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
super.touchesBegan(touches, withEvent: event)
guard let location = touches.first?.locationInNode(self),
let scene = scene,
nodeAtPoint(location) == "Game Button" else {
return
}
let transition = SKTransition.reveal(
with: .down,
duration: 1.0
)
let nextScene = GameScene(size: scene.size)
nextScene.scaleMode = .aspectFill
scene.view?.presentScene(nextScene, transition: transition)
}
if you have to work on touch-begain or node action , Then use it:
override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) {
let touch = touches.anyObject() as UITouch
if CGRectContainsPoint(btncloseJump.frame, touch.locationInNode(self)) {
self.scene.removeFromParent()
btncloseJump.removeFromParent()
let skView = self.view as SKView
skView.ignoresSiblingOrder = true
var scene: HomeScene!
scene = HomeScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
skView.presentScene(scene, transition: SKTransition.fadeWithColor(SKColor(red: 25.0/255.0, green: 55.0/255.0, blue: 12.0/255.0, alpha: 1), duration: 1.0))
}
}