在应用程序启动/退出时暂停spritekit游戏.. iOS8

时间:2014-10-11 17:55:43

标签: ios swift ios8 sprite-kit nsnotificationcenter

我已经阅读了有关此主题的所有内容,但仍然无法弄清楚我的问题。我试过在appdelegate的每个区域暂停我的游戏

func applicationWillResignActive(application: UIApplication!) {
    NSNotificationCenter.defaultCenter().postNotificationName("pauseGameScene", object: self)
}

func applicationDidEnterBackground(application: UIApplication!) {
    NSNotificationCenter.defaultCenter().postNotificationName("pauseGameScene", object: self)
}

func applicationWillEnterForeground(application: UIApplication!) {
    NSNotificationCenter.defaultCenter().postNotificationName("pauseGameScene", object: self)
}

func applicationDidBecomeActive(application: UIApplication!) {
    NSNotificationCenter.defaultCenter().postNotificationName("pauseGameScene", object: self)
}

在我的控制器中:

override func viewDidLoad() {
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "pauseGame:", name: "pauseGameScene", object: nil)
}

func pauseGame(){
    self.skView.paused = true
    self.skView.scene!.paused = true
}

我知道pauseGame有效,因为如果我用场景中的按钮切换它,它将停止游戏。即使我将skview和场景加载到控制器后直接暂停我的场景和场景......游戏也不会在启动时暂停。我在游戏中很容易暂停游戏。但出于某种原因,每当我退出并恢复应用程序时,游戏都会自行暂停。

我注意到,如果我得到hacky并使用某种延迟..我可以让它工作。但显然这是非常愚蠢的......我只需要知道游戏本身在哪里取消!

func delay(delay:Double, closure:()->()) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue(), closure)
}

func pauseGame(sender: UIButton!){

    delay(2) {
        println("blah")
        self.skView.paused = true
        self.skView.scene!.paused = true
    }
}

3 个答案:

答案 0 :(得分:7)

这是一种在从后台模式返回后保持视图暂停的方法。

Xcode 7 (请参阅下面的Xcode 8说明)

在故事板中,

1)将视图的类更改为MyView

在视图控制器中,

2)使用名为stayPaused的布尔值

定义一个SKView子类
class MyView: SKView {
    var stayPaused = false

    override var paused: Bool {
        get {
            return super.paused
        }
        set {
            if (!stayPaused) {
                super.paused = newValue
            }
            stayPaused = false
        }
    }

    func setStayPaused() {
        if (super.paused) {
            self.stayPaused = true
        }
    }
}

3)将视图定义为MyView

4)添加通知程序以设置stayPaused标志

class GameViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
            // Configure the view.
            let skView = self.view as MyView

            NSNotificationCenter.defaultCenter().addObserver(skView, selector:Selector("setStayPaused"), name: "stayPausedNotification", object: nil)

在App Delegate中,

5)发布通知以在应用变为活动时设置停留暂停标志

func applicationDidBecomeActive(application: UIApplication) {
    NSNotificationCenter.defaultCenter().postNotificationName("stayPausedNotification", object:nil)
}

Xcode 8

在故事板中,

1)将视图的类别从SKView更改为MyView

在视图控制器中,

2)使用名为stayPaused的布尔值

定义SKView子类
class MyView: SKView {
    var stayPaused = false

    override var isPaused: Bool {
        get {
            return super.isPaused
        }
        set {
            if (!stayPaused) {
                super.isPaused = newValue
            }
            stayPaused = false
        }
    }

    func setStayPaused() {
        if (super.isPaused) {
            self.stayPaused = true
        }
    }
}

3)将视图定义为MyView

4)添加通知程序以设置stayPaused标志

class GameViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        if let view = self.view as! MyView? {
            NotificationCenter.default.addObserver(view, selector:#selector(MyView.setStayPaused), name: NSNotification.Name(rawValue: "stayPausedNotification"), object: nil)

在App Delegate中,

5)发布通知以在应用变为活动时设置停留暂停标志

func applicationDidBecomeActive(_ application: UIApplication) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "stayPausedNotification"), object: nil)
}

答案 1 :(得分:2)

这是一个完全基于0x141E给出的答案的Obj-C示例,没有子类化视图。在我的情况下,因为我有内部游戏状态,如已完成,暂停和启动,我不得不对覆盖的setPaused:方法进行额外检查。但这对我来说完美无瑕,绝对是一种可行的方式。

<强> AppDelegate.m

- (void)applicationDidBecomeActive:(UIApplication *)application {

    [[NSNotificationCenter defaultCenter] postNotificationName:@"stayPausedNotification" object:nil];
}

<强> GameScene.m

@interface GameScene()

@property (nonatomic, assign) BOOL stayPaused;

@end

@implementation GameScene

//Use initWithCoder: if you load a scene from .sks file, because initWithSize is not called in that case.

-(instancetype)initWithSize:(CGSize)size{ 

    if(self = [super initWithSize:size]){

        _stayPaused = NO;


         //register to listen for event
        [[NSNotificationCenter defaultCenter]
         addObserver:self
         selector:@selector(setStayPaused)
         name:@"stayPausedNotification"
         object:nil ];
    }
    return self;
}

-(void)setStayPaused{

    self.stayPaused = YES;
}

-(void)setPaused:(BOOL)paused{

    if (!self.stayPaused) {
        [super setPaused:paused];
    }
    self.stayPaused = NO;
}

-(void)willMoveFromView:(SKView *)view{

    [[NSNotificationCenter defaultCenter] removeObserver:self  name:@"stayPausedNotification" object:nil];
}

@end

答案 2 :(得分:0)

我最近遇到了同样的问题。 stayPaused解决方案对我来说很好。谢谢你们:))

但是,我认为您用来设置stayPaused的机制并不健全。只是通过调用setStayPaused一次在App上变得活跃是不够的,苹果的工程师可能会改变Sprite Kit的代码并调用setPaused(false)来激活更多(事实上,我认为他们刚刚做了!)。当您在第一次通话时将stayPaused设置为false时,第二个setPaused(false)将恢复游戏。

我的建议是直接在pauseGame / resumeGame函数中设置stayPaused属性,并删除&#34; self.stayPaused = NO;&#34;来自setPaused函数。通过这种方式,SpriteKit的默认行为可以随心所欲,但只要我们想要,游戏就会暂停。