Reputation: 315
Okay, I have a scene in which I have this method, createSceneContents, that gets called when didMoveToView gets called. In this method I have a couple of things that create the scenes, including a timer that spawns nodes like this:
self.spawningSpeed = 1.5;
self.enemyData = [[Enemy alloc]init];
SKAction *wait = [SKAction waitForDuration:1.5];
SKAction *run = [SKAction performSelector:@selector(spawningEnemy) onTarget:self];
self.spawnAction = [SKAction repeatActionForever:[SKAction sequence:@[wait,run]]];
[self.world runAction:self.spawnAction withKey:@"spawn"];
enemyData is an object of my enemy class which basically just adds a SKSpriteNode to the scene. The world node is simply a node that I add all the game elements to.
This is what happens in the spawningEnemy method:
-(void)spawningEnemy {
NSLog(@"spawned");
SKSpriteNode *aNewEnemy = [self.enemyData createEnemyWithSize:self.customUnit andWidth:self.frame.size.width andHeight:self.frame.size.height + self.player.position.y];
aNewEnemy.physicsBody.allowsRotation = NO;
aNewEnemy.physicsBody.categoryBitMask = self.enemyCategory;
aNewEnemy.physicsBody.collisionBitMask = self.enemyCategory | self.playerCategory | self.edgeCategory | self.bottomCategory;
aNewEnemy.physicsBody.contactTestBitMask = self.enemyCategory | self.playerCategory | self.edgeCategory | self.bottomCategory;
[self.world addChild:aNewEnemy];
}
This just gets an SKSpriteNode from the enemy class and sets some properties. It also adds it to the world.
I also have 4 methods that pause, resume, restart and game-over the game:
-(void)pauseGame {
[self createPauseMenu];
NSLog(@"Pausing...");
self.world.paused = YES;
self.isPaused = YES;
}
-(void)restartGame {
[self removeAllChildren];
[self removeAllActions];
self.enemyData = nil;
self.isPaused = NO;
[self createSceneContents];
}
-(void)resumeGame {
self.isPaused = NO;
self.world.paused = NO;
}
-(void)gameOver {
NSLog(@"Game Over");
self.world.paused = YES;
self.isPaused = YES;
}
There's more in these methods, but this is all that really matters.
Now here's the problem: This all works fine until I exit the app. When returning to the app, the game automatically calls the pause method, but then I hit restart or resume, the spawningEnemy method is not being called. (I checked with an NSLog message as you can see)
What might have caused this?
Upvotes: 2
Views: 130
Reputation: 11696
I have tried the below code and it works. The spawning stops when the app resigns active and starts itself again once the app becomes active again.
You do not need to manually include code to pause as SpriteKit will pause itself when resigning active but I included it to show how to communicate between the AppDelegate and SKScene.
AppDelegate.m
- (void)applicationWillResignActive:(UIApplication *)application {
[[NSNotificationCenter defaultCenter]postNotificationName:@"applicationWillResignActive" object:self];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[NSNotificationCenter defaultCenter]postNotificationName:@"applicationDidBecomeActive" object:self];
}
GameScene.m
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
SKAction *wait = [SKAction waitForDuration:1.5];
SKAction *run = [SKAction performSelector:@selector(spawningEnemy) onTarget:self];
SKAction *spawnAction = [SKAction repeatActionForever:[SKAction sequence:@[wait,run]]];
[self runAction:spawnAction withKey:@"spawn"];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(pauseGame)
name:@"applicationWillResignActive"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(resumeGame)
name:@"applicationDidBecomeActive"
object:nil];
}
return self;
}
-(void)spawningEnemy {
NSLog(@"spawningEnemy");
}
-(void)pauseGame {
NSLog(@"applicationWillResignActive...");
self.paused = YES;
}
-(void)resumeGame {
NSLog(@"applicationDidBecomeActive...");
self.paused = NO;
}
-(void)willMoveFromView:(SKView *)view {
// good housekeeping
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Upvotes: 1
Reputation: 516
If it is the whole scene that you want to have paused, then you should only pause the SKView containing the scene. This will pause all animations, run loops and interaction of the scene and all nodes within the scene.
Also experience learned me that it is good practice to pause the scene when the application goes to the background and resume when it returnes to the foreground. It prevents issues such as: Sprite Kit & playing sound leads to app termination
Upvotes: 0