返回 App SpriteKit 后按播放

Posted

技术标签:

【中文标题】返回 App SpriteKit 后按播放【英文标题】:Pressing play after returning to App SpriteKit 【发布时间】:2016-04-15 21:55:18 【问题描述】:

APP DELEGATE 崩溃问题

我是编程的初学者,在开发我的应用程序时,出现了一个无法解决的问题。当用户离开应用程序本身时,我尝试暂停游戏,当需要返回时,游戏暂停,因为按下主页按钮。我的困难是,当用户在游戏未暂停的情况下离开应用程序并返回时,它可以完美运行,但是当用户暂停游戏并离开时,Xcode 向我显示一条错误消息:“线程 1:信号 SIGARBT em>”,游戏就崩溃了。如果你看看我的游戏,我会很高兴的

自行编码

AppDelegate.swift

func applicationWillResignActive(application: UIApplication) 
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.

    //pause when leaving app
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("pauseState"), name: "pauseState", object: nil)

GameScene.swift

import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate 

var gameLayer = SKNode()
var pauseLayer = SKNode()

var gameStarted = Bool()

var pauseButton = SKSpriteNode()
var playButton = SKSpriteNode()

func setupPauseButton()

    //Pause
    pauseButton = SKSpriteNode (imageNamed: "pause")
    pauseButton.setScale(0.25)
    pauseButton.position = CGPoint(x: self.frame.width / 10, y: self.frame.height / 1.5)
    //pauseButton.zPosition = 3

func setupPlayButton()

    //Play
    playButton = SKSpriteNode (imageNamed: "play")
    playButton.setScale(0.15)
    playButton.position = CGPoint(x: self.frame.width / 10, y: self.frame.height / 1.5)
    //playButton.zPosition = 3


//layers
func createGameLayer()

    self.physicsWorld.contactDelegate = self

    setupPauseButton()
    gameLayer.addChild(pauseButton) //add pauseButton to gameLayer
    pauseButton.hidden = true

func createPauseLayer()

    //Play
    setupPlayButton()
    pauseLayer.addChild(playButton) //add playButton to pauseLayer


override func didMoveToView(view: SKView) 
/* Setup your scene here */

    //pause when coming back
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("pauseState"), name: "pauseState", object: nil)

    self.addChild(gameLayer)

    createGameLayer()
    createPauseLayer()


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) 
/* Called when a touch begins */

    //run only if game is running
    if gameLayer.paused == false

        //pauseButton shows when starting to play
        pauseButton.hidden = false
    

    //when touch buttons/screen
    for touch in touches

        let location = touch.locationInNode(self)
        let node = nodeAtPoint(location)

        if node == pauseButton
            pauseState()
        

        else if node == playButton
            playState()
        

        else

            if gameStarted == false  //game didn't start yet

                gameStarted = true

                Character.physicsBody?.affectedByGravity = true //start falling when touch the screen

                //first jump
                Character.physicsBody?.velocity = CGVectorMake(0, 0)
                Character.physicsBody?.applyImpulse(CGVectorMake(0, 15))
                
            
            else

                //jump
                Character.physicsBody?.velocity = CGVectorMake(0, 0)
                Character.physicsBody?.applyImpulse(CGVectorMake(0, 15))
                
            
        
    


//states
func pauseState()

    pauseButton.hidden = true //hide pauseButton
    self.physicsWorld.speed = 0 //pause physics (character, etc)
    gameLayer.paused = true //pause gameLayer

    self.addChild(pauseLayer) //add pauseLayer

func playState()

    pauseLayer.removeFromParent() //remove pauseLayer

    gameLayer.paused = false //unpause gameLayer
    self.physicsWorld.speed = 1 //unpause physics (character, etc)
    pauseButton.hidden = false //show pauseButton


override func update(currentTime: CFTimeInterval) 
    /* Called before each frame is rendered */



【问题讨论】:

访问raywenderlich.com/10209/my-app-crashed-now-what-part-1了解如何调试崩溃 【参考方案1】:

我在您的代码中注意到的两件事

1) 从 swift 2.2 开始,苹果终于将选择器方法从字符串中更改了。所以在你的 gameScene 中将观察者更改为这个。

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(GameScene.pauseState), name: "pauseState", object: nil)

https://medium.com/swift-programming/swift-selector-syntax-sugar-81c8a8b10df3#.kncj5thdh

2) 在您的应用委托中,您正在添加另一个没有意义的观察者。您想将通知发布给您在 GameScene 中的观察者。

改成这个

NSNotificationCenter.defaultCenter().postNotificationName("pauseState", object: nil)

3) 不确定您是否正在这样做,但始终建议您在离开场景时删除任何 NSNotification 观察者。拨打此行

NSNotificationCenter.defaultCenter().removeObserver(self)

当你过渡到新场景或在 GameScenes 中的“WillMoveFromView”方法中

如果您遵循苹果命名约定,这也是一个好主意。只有类、结构、枚举和协议应该以大写字母开头。这使您的代码对您自己和在 SO 上更具可读性(您的代码标记为蓝色,但不应该)

希望这会有所帮助。

【讨论】:

以上是关于返回 App SpriteKit 后按播放的主要内容,如果未能解决你的问题,请参考以下文章

Swift / Spritekit:通过特定场景播放音乐

从 SpriteKit 中的类播放音频

在不同的 UIKit 和 SpriteKit 场景中连续播放音频

SpriteKit 中的循环背景音乐

如果 spritekit 中正在播放来自另一个应用程序的音乐,如何使 AVAudioPlayer 静音

在 Swift SpriteKit 项目中播放声音?