The "Done" button in Game Center will not dismiss the controller. My code to dismiss the view controller is exactly the same everywhere I look. I've looked at similar questions on here but no luck. Can anyone help me?
GameScene.Swift (This serves as my start menu )
class GameScene: SKScene, GKGameCenterControllerDelegate {
var startBtn = SKSpriteNode(imageNamed: "play button")
var title = SKLabelNode(fontNamed: "AvenirNext-UltraLight")
var leaderboardButtonImage = SKSpriteNode(imageNamed: "leaderboard button")
override func didMoveToView(view: SKView) {
let bounds = UIScreen.mainScreen().bounds
self.scene?.size = CGSize(width: bounds.size.width, height: bounds.size.height)
scene?.backgroundColor = UIColor.whiteColor()
startBtn.position = CGPoint(x: self.frame.width / 2 - 100, y: self.frame.height / 2)
startBtn.size = CGSize(width: 140, height: 55)
self.addChild(startBtn)
leaderboardButtonImage.position = CGPoint(x: self.frame.width / 2 + 100, y: self.frame.height / 2)
leaderboardButtonImage.size = CGSize(width: 140, height: 55)
self.addChild(leaderboardButtonImage)
}
func showLeaderboard() {
let vc = self.view?.window?.rootViewController
let gc = GKGameCenterViewController()
gc.viewState = GKGameCenterViewControllerState.Leaderboards
gc.leaderboardIdentifier = "I removed this part"
vc!.presentViewController(gc, animated: true, completion: nil)
}
func gameCenterViewControllerDidFinish(gameCenterViewController: GKGameCenterViewController) {
gameCenterViewController.dismissViewControllerAnimated(true, completion: nil)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch in (touches ) {
let location = touch.locationInNode(self)
if (startBtn.containsPoint(location)) {
self.view?.presentScene(GamePlayScene(), transition: SKTransition.crossFadeWithDuration(1.0))
GamePlayScene().scaleMode = .ResizeFill
startBtn.removeFromParent()
title.removeFromParent()
leaderboardButtonImage.removeFromParent()
}
if (leaderboardButtonImage.containsPoint(location)) {
showLeaderboard()
}
}
}
}
In my func showLeaderboard(), I had to add the line gc.gameCenterDelegate = self which made the "Done" button work.
I hope other people who have this same problem see this potential fix.
func showLeaderboard() {
let vc = self.view?.window?.rootViewController
let gc = GKGameCenterViewController()
gc.viewState = GKGameCenterViewControllerState.Leaderboards
gc.gameCenterDelegate = self
gc.leaderboardIdentifier = "I removed this part"
vc!.presentViewController(gc, animated: true, completion: nil)
}
Related
I want to click a button to spawn a 3D object. I overlayed a SpritKit Scene onto a SceneKit Scene to use SKNodes in my interface. But for some reason the function is not being called, the rest of the code seems to be working. I would like to know the reason for this, and if there is another way of calling this function
This is the function I'm trying to pass.
func setupDice() {
var diceNode: SCNNode!
let size: CGFloat = 1.5
let diceGeometry = SCNBox(width: size, height: size, length: size, chamferRadius: 0)
diceGeometry.materials.removeFirst()
for i in 1...6 {
let diceMaterial = SCNMaterial()
diceMaterial.locksAmbientWithDiffuse = true
diceMaterial.diffuse.contents = UIImage(named: "x\(i)")?.xFlipped
diceMaterial.blendMode = .multiply
diceGeometry.materials.append(diceMaterial)
}
diceNode = SCNNode(geometry: diceGeometry)
diceNode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
diceNode.physicsBody?.restitution = 1
diceNode.physicsBody?.mass = 1
diceNode.physicsBody?.categoryBitMask = 1
diceNode.physicsBody?.collisionBitMask = 2
diceNode.physicsBody?.applyTorque(SCNVector4(x: randomTorqueForce(),
y: randomTorqueForce(),
z: randomTorqueForce(),
w: randomTorqueForce()), asImpulse: true)
self.rootNode.addChildNode(diceNode)
}
This is where I'm calling the function inside of my SpriteKit Scene
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
if touch == touches.first {
if playButtom.contains(touch.location(in: self)){
mainScene.setupDice()
}
}
}
}
and this is the correct state of my GameViewController
class GameViewController: UIViewController {
var sceneView: SCNView!
var spriteScene: OverlayScene!
override func viewDidLoad() {
super.viewDidLoad()
//setupTest()
self.sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
self.sceneView.scene = MainScene()
spriteScene = OverlayScene(size: view.bounds.size)
sceneView.backgroundColor = UIColor.white
sceneView.overlaySKScene = spriteScene
sceneView.allowsCameraControl = true
sceneView.isPlaying = true
self.view.addSubview(self.sceneView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Probably because you didn't set the mainScene property during the initialization phase of your OverlayScene. Something like this should works:
class GameViewController: UIViewController {
var sceneView: SCNView!
var spriteScene: OverlayScene!
override func viewDidLoad() {
super.viewDidLoad()
//setupTest()
self.sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
let mainScene = MainScene()
self.sceneView.scene = mainScene
let overlayScene = OverlayScene(size: view.bounds.size)
overlayScene.mainScene = mainScene
spriteScene = overlayScene
sceneView.backgroundColor = UIColor.white
sceneView.overlaySKScene = spriteScene
sceneView.allowsCameraControl = true
sceneView.isPlaying = true
self.view.addSubview(self.sceneView)
}
I am trying to play a sound when the UIButton: "StartButton" is clicked. However, I get an error that reads:
Argument type 'CGPoint' does not conform to expected type 'UIFocusEnvironment'
I created the button as below and assigned a CGRect poisiton to it, and I am trying to use the touchesBeagn function to detect the location of the touch and determine if it matches the location of the Button and if so call playButtonSound() function.
This is my code in the MainMenu.swift file:
// MainMenuScene.swift
import Foundation
import SpriteKit
import AVFoundation
let startButton:UIButton = UIButton(type: UIButtonType.roundedRect)
class MainMenuScene: SKScene
{
var buttonSound = AVAudioPlayer()
override func didMove(to view: SKView) {
let background = SKSpriteNode(imageNamed: "background")
background.size = self.size
background.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
background.zPosition = 0
self.addChild(background)
let menuLabel1 = SKLabelNode(fontNamed: "The Bold Font")
menuLabel1.text = "Hit"
menuLabel1.position = CGPoint(x: self.size.width * 0.45, y: self.size.height * 0.78)
menuLabel1.fontSize = 300
menuLabel1.fontColor = UIColor.yellow
menuLabel1.colorBlendFactor = 1
menuLabel1.zPosition = 1
self.addChild(menuLabel1)
let menuLabel2 = SKLabelNode(fontNamed: "The Bold Font")
menuLabel2.text = "&"
menuLabel2.position = CGPoint(x: self.size.width * 0.55, y: self.size.height * 0.64)
menuLabel2.fontSize = 350
menuLabel2.fontColor = UIColor.red
menuLabel2.colorBlendFactor = 1
menuLabel2.zPosition = 1
self.addChild(menuLabel2)
let menuLabel3 = SKLabelNode(fontNamed: "The Bold Font")
menuLabel3.text = "Go"
menuLabel3.position = CGPoint(x: self.size.width * 0.60, y: self.size.height * 0.52)
menuLabel3.fontSize = 300
menuLabel3.fontColor = UIColor.yellow
menuLabel3.colorBlendFactor = 1
menuLabel3.zPosition = 1
self.addChild(menuLabel3)
startButton.frame = CGRect(x: (self.view?.center.x)! * 0.5 , y: (self.view?.center.y)! * 1.5 , width: 200, height: 50)
startButton.backgroundColor = .red
startButton.setTitleColor(.white, for: .normal)
startButton.titleLabel?.adjustsFontSizeToFitWidth = true
startButton.layer.cornerRadius = 10
startButton.clipsToBounds = true
startButton.setTitle("Start Game", for: .normal)
startButton.titleLabel!.font = UIFont(name: "The Bold Font", size: 60)
startButton.addTarget(self, action:#selector(self.startButtonClicked), for: .touchUpInside)
self.view?.addSubview(startButton)
}
#objc func startButtonClicked() {
let sceneToMoveTo = GameScene(size: self.size)
sceneToMoveTo.scaleMode = self.scaleMode
let myTransition = SKTransition.reveal(with: .right , duration: 0.5)
self.view!.presentScene(sceneToMoveTo, transition: myTransition)
}
#objc func playButtonSound(filename: String) {
let url = Bundle.main.url(forResource: "button.mp3" , withExtension: nil)
guard let newURL = url else {
print("Could not find file: \(filename)")
return
}
do {
buttonSound = try AVAudioPlayer(contentsOf: newURL)
buttonSound.numberOfLoops = -1
buttonSound.prepareToPlay()
buttonSound.setVolume(0.50, fadeDuration: 0.1)
buttonSound.play()
} catch let error as NSError {
print(error.description)
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch: AnyObject in touches {
var pointOfTouch = touch.location(in: self)
if startButton.contains(pointOfTouch)
{
playButtonSound(filename: "button.mp3")
}
}
}
}
What is the reason for the error?
The problem is that you are calling the wrong contains method.
You are calling the method on UIButton, which has this signature:
public func contains(_ environment: UIFocusEnvironment) -> Bool
What you probably meant to call was the method on the button's frame:
if startButton.frame.contains(pointOfTouch)
You may want to read the docs to make sure that using the frame is what you want.
I tried to add sound when button pressed but when I press the button no sound. No mistakes in terminal.
I already tried compile on another computer, and debug on iPhone.
No sound persist.
Please help me solve this problem.
class MenuScene : SKScene {
let txtAtlas : SKTextureAtlas = SKTextureAtlas(named: "UI.atlas")
let txtAtlas2 : SKTextureAtlas = SKTextureAtlas(named: "mapbc.atlas")
let startBut = SKSpriteNode()
let tssound = SKAction.playSoundFileNamed("tssound.wav", waitForCompletion: false)
override func didMove(to view: SKView) {
self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
self.backgroundColor = UIColor.black
let logo = SKLabelNode(fontNamed: "Helvetica")
logo.text = "Train Control"
logo.position = CGPoint(x: 0, y: 100)
logo.fontSize = 60
logo.fontColor = UIColor.green
self.addChild(logo)
startBut.texture = txtAtlas.textureNamed("stbut.png")
startBut.size = CGSize(width: 230, height: 85)
startBut.position = CGPoint(x: 0, y: -20)
startBut.name = "StartBtn"
self.addChild(startBut)
let startText = SKLabelNode(fontNamed: "AvenirNext-HeavyItalic")
startText.text = "Start Manage!"
startText.verticalAlignmentMode = .center
startText.position = CGPoint(x: 0, y: 2)
startText.fontSize = 30
startText.name = "StartBtn"
startBut.addChild(startText)
let bcmap = SKSpriteNode()
bcmap.texture = txtAtlas2.textureNamed("mapbc.png")
bcmap.zPosition = -1
bcmap.size = CGSize(width: 400.0, height: 350.0)
bcmap.position = CGPoint(x: -100, y: 0)
bcmap.alpha = 0.7
self.addChild(bcmap)
let stbutaction = SKAction.sequence([SKAction.fadeAlpha(to: 0.7, duration: 0.9),
SKAction.fadeAlpha(to: 1.0, duration: 0.9)])
startBut.run(SKAction.repeatForever(stbutaction))
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches) {
let location = touch.location(in: self)
let nodeTouched = atPoint(location)
if nodeTouched.name == "StartBtn" {
// Player touched the start text or button node
self.view?.presentScene(GameScene(size: self.size))
self.run(tssound)
}
}
}
}
You should probably initialise and run your sound inside GameScene e.g. when the scene loads. You are trying to run the sound on MenuScene which doesn't exist after you have transitioned to GameScene
I tried to move between GameScene to SettingsScene and is works perfect expect first time.
In first time the game is "stuck" for 1-3 seconds and presented the SettingsScene without the transition, after first time the transition and game works perfect.
The back (between SettingsScene to GameScene) works good also in first time.
The transition code between GameScene to SettingsScene
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch: AnyObject in touches {
self.removeAllActions()
// Get the location of the touch in this scene
let location = touch.location(in: self)
// Check if the location of the touch is within the button's bounds
//Play Button
if PlayButton.contains(location) {
bannerView.isHidden = true
let newScene = PlayScene(size: (view?.bounds.size)!)
newScene.scaleMode = .aspectFill
let reveal = SKTransition.crossFade(withDuration: 1.0)
self.view?.presentScene(newScene, transition: reveal)
//Settings Button
}else if SettingsButton.contains(location) {
bannerView.isHidden = true
settingsscene?.scaleMode = .resizeFill
let reveal = SKTransition.push(with: SKTransitionDirection.down, duration: 0.7)
self.view?.presentScene(settingsscene!, transition: reveal)
}
}
}
GameScene:
var settingsscene: SKScene?
override func didMove(to view: SKView) {
/* Setup your scene here */
//
let size = self.size
DispatchQueue.global(qos: DispatchQoS.QoSClass.background).async {
[weak self] () -> Void in
self?.settingsscene = SettingsScene(size: (view.bounds.size))
}
SettingsScene:
override func didMove(to view: SKView) {
//Settings Background
settingsBackground.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2)
settingsBackground.zPosition = -1
}
override init(size: CGSize) {
super.init()
//Settings Label
settingsLabel.text = "Settings"
settingsLabel.fontName = "AvenirNext-Bold"
settingsLabel.fontColor = UIColor.white
settingsLabel.horizontalAlignmentMode = .center
settingsLabel.verticalAlignmentMode = .center
adjustLabelFontSizeToFitRect(labelNode: settingsLabel, rect: CGRect(x:self.frame.midX, y:self.frame.midY, width: 180, height: 110), center: true)
settingsLabel.setScale(self.frame.width * 0.001)
settingsLabel.position = CGPoint(x: self.frame.midX, y: self.frame.maxY - settingsLabel.frame.height)
settingsLabel.zPosition = 1
addChild(settingsLabel)
/**** Labels ****/
//Sounds Label
soundsLabel.text = "Sounds"
soundsLabel.fontName = "AvenirNext"
soundsLabel.fontColor = UIColor.white
adjustLabelFontSizeToFitRect(labelNode: soundsLabel, rect: CGRect(x:self.frame.midX, y:settingsLabel.position.y - 20, width:110, height: 70), center: true)
soundsLabel.setScale(self.frame.width * 0.001)
soundsLabel.zPosition = 1
//Rate Label
rateLabel.text = "Rate Game"
rateLabel.fontName = "AvenirNext"
rateLabel.fontColor = UIColor.white
adjustLabelFontSizeToFitRect(labelNode: rateLabel, rect: CGRect(x:self.frame.midX, y:50, width:120, height: 110), center: true)
rateLabel.setScale(frame.width * 0.001)
rateLabel.zPosition = 1
//Twitter Label (Follow me)
twiterLabel.text = "Follow me"
twiterLabel.fontName = "AvenirNext"
twiterLabel.fontColor = UIColor.white
adjustLabelFontSizeToFitRect(labelNode: twiterLabel, rect: CGRect(x:self.frame.midX, y:10, width:17, height: 110), center: true)
twiterLabel.setScale(frame.width * 0.001)
twiterLabel.zPosition = 1
//iAP Label (Remove Ads)
iapLabel.text = "Remove Ads"
iapLabel.fontName = "AvenirNext"
iapLabel.fontColor = UIColor.white
adjustLabelFontSizeToFitRect(labelNode: iapLabel, rect: CGRect(x:self.frame.midX, y:70, width:40, height: 110), center: true)
iapLabel.setScale(frame.width * 0.001)
iapLabel.zPosition = 1
//Restore iAP Label
restoreLabel.text = "Restore Purchase"
restoreLabel.fontName = "AvenirNext"
restoreLabel.fontColor = UIColor.white
adjustLabelFontSizeToFitRect(labelNode: restoreLabel, rect: CGRect(x:self.frame.midX, y:308, width:102, height: 110), center: true)
restoreLabel.setScale(frame.width * 0.001)
restoreLabel.zPosition = 1
//About Label
aboutLabel.text = "Restore Purchase"
aboutLabel.fontName = "AvenirNext"
aboutLabel.fontColor = UIColor.white
adjustLabelFontSizeToFitRect(labelNode: aboutLabel, rect: CGRect(x:self.frame.midX, y:18, width:123, height: 312), center: true)
aboutLabel.setScale(frame.width * 0.001)
aboutLabel.zPosition = 1
//Back Button
backButton.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
backButton.zPosition = 1
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func SettingsSetup() {
addChild(settingsBackground)
addChild(myLabels)
addChild(backButton)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch:AnyObject in touches {
let location = touch.location(in:self)
//BackButton Action
if backButton.contains(location) {
let newScene = GameScene(fileNamed: "GameScene")
newScene?.scaleMode = .aspectFill
let reveal = SKTransition.push(with: SKTransitionDirection.up, duration: 0.7)
self.view?.presentScene(newScene!, transition: reveal)
}
}
}
How can I fix it?
How to use protocol? I can't use it. I just wanna print out "abc" when I click the start button. It didn't work. plz help me
import UIKit
import SpriteKit
protocol GameDelegate {
func gameOver()
}
class MainMenuScene: SKScene
{
var Gdelegate: GameDelegate?
override func didMoveToView(view: SKView)
{
let background = SKSpriteNode(imageNamed: "DiscsBackground")
background.size = self.size
background.zPosition = 0
background.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
self.addChild(background)
let gameTitleLabel1 = SKLabelNode(fontNamed: "Pusab")
gameTitleLabel1.text = "Disappearing"
gameTitleLabel1.fontSize = 90
gameTitleLabel1.fontColor = SKColor.whiteColor()
gameTitleLabel1.position = CGPoint(x: self.size.width/2, y: self.size.height*0.75)
gameTitleLabel1.zPosition = 1
self.addChild(gameTitleLabel1)
let gameTitleLabel2 = SKLabelNode(fontNamed: "Pusab")
gameTitleLabel2.text = "Discs"
gameTitleLabel2.fontSize = 250
gameTitleLabel2.fontColor = SKColor.whiteColor()
gameTitleLabel2.position = CGPoint(x: self.size.width/2, y: self.size.height*0.6)
gameTitleLabel2.zPosition = 1
self.addChild(gameTitleLabel2)
let gameByLabel = SKLabelNode(fontNamed: "Pusab")
gameByLabel.text = "Disappearing"
gameByLabel.fontSize = 90
gameByLabel.fontColor = SKColor.whiteColor()
gameTitleLabel2.position = CGPoint(x: self.size.width/2, y: self.size.height*0.95)
gameByLabel.zPosition = 1
self.addChild(gameByLabel)
let startLabel = SKLabelNode(fontNamed: "Pusab")
startLabel.text = "start"
startLabel.fontSize = 150
startLabel.fontColor = SKColor.whiteColor()
startLabel.position = CGPoint(x: self.size.width/2, y: self.size.height*0.35)
startLabel.zPosition = 1
startLabel.name = "startButton"
self.addChild(startLabel)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
for touch: AnyObject in touches
{
let pointOfTouch = touch.locationInNode(self)
let tappedNode = nodeAtPoint(pointOfTouch)
let tappedNodeName = tappedNode.name
if tappedNodeName == "startButton"
{
//self.scene?.view?.presentScene(nil)
Gdelegate?.gameOver()
}
}
}
}
class MHAGameViewController: UIViewController,GameDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let scene = MainMenuScene(size: CGSize(width: 1536, height: 2048))
// 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)
}
func gameOver() {/*
self.performSegueWithIdentifier("segue1", sender: self)
let alertController = UIAlertController(title: "HELP", message:
"Please wait....", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "close", style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)*/
print("abc")
}
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
}
}
You should set the delegate as follow :
let scene = MainMenuScene(size: CGSize(width: 1536, height: 2048))
scene.Gdelegate = self
Step: 1 - Declare protocol Just before class Declaration and Below Import stmt. (Inside Cell Class)
protocol BtnsAction: NSObjectProtocol
{
func btnLearnAction(_ sender: Any?)
}
weak var delegate: BtnsAction?
Step: 2 - Declare Button Action Method inside Cell Class.
#IBAction func btnLearnMoreAction(_ sender: UIButton) {
self.delegate?.btnLearnAction(self)
}
Step: 3 - Now, Inside ViewController.
class MyViewController_VC:ViewController, BtnsAction
//MARK: - Protocol Method -
func btnLearnAction(_ sender: Any?) {
let cell = sender as! SubCategoryCell
let indexpath = self.TableView1.indexPath(for: cell)
let dictData = self.arrFree_Listing[(indexpath?.row)!] as! NSMutableDictionary
let strId = String(dictData.value(forKey: "id") as! Int)
let detailVC = self.storyboard?.instantiateViewController(withIdentifier: "ListingDetails_InnerVC") as! ListingDetails_InnerVC
detailVC.strID = strId
self.navigationController?.pushViewController(detailVC, animated: true)
}
**Don't Forget to add **
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "_Cell") as! _Cell
cell.delegate = self
return cell
}