pause spritekit scene and show "paused" label - ios

I want to show a "paused" SKLabelNode when someone clicks on the screen and therefore pauses the sprite kit game.
So I have in touchesBegan ->
[self.pausedLabel setHidden:!self.pausedLabel.hidden];
[self.scene.view setPaused:!self.scene.view.paused];
The Game is paused correctly but the SKLabelNode is not shown (scene not rendered before paused?!)
If I add a NSTimer for pausing the scene the label is shown, but then the game continues for that timer-time.
Does anyone have a better solution for this?
Thanks in advance

I would use SKAction for this. You can use +runBlock: to add the code related to hiding the label, and then use the -runAction method with the completion handler to pause the scene. The runBlock: method may return immediately, but this way, the screen manages to update before the scene is paused.
SKAction *action = [SKAction runBlock:^{
[self.pausedLabel setHidden:!self.pausedLabel.hidden];
}];
[self.pausedLabel runAction:action completion:^{
[self.scene.view setPaused:!self.scene.paused];
}];

Just use a state ivar to determine if the scene should update its content or not.
When you click the button set this state to PAUSE and in your scene frame update loop test the state.
if (_state != PAUSE) {// Use enum for the state var
// Update scene objects
}
when your button is clicked:
Add pause label to scene
Set state to PAUSE
The benefits of this approach is that it allows you to decide exactly what will happen on pause (opposing to pausing the whole scene). You can animate a cool background while in pause or do anything you'd like as this is totally in your control

Related

Pausing and Playing SpriteKit Game in Swift

How do I pause and resume a game in SpriteKit in a single Scene Game (gameScene)?
addChild(pauseText)
self.runAction(SKAction.runBlock(self.pauseGame))
To pause a game from the view controller, you should call gameView.paused = true (where gameView is an SKView).
To pause a game from the scene itself, you should call physicsWorld.speed = 0. To un-pause the game, call physicsWorld.speed = 1.

How do I get to know what sprite has been touched?

I have some sprites coming from the bottom of the screen in a random order. I want to swipe the sprite in the direction of the swipe. I got the algorithm for swiping. Also, I get an NSLog message whenever any sprite has been touched in the screen. The NSLog gives correct responses to any and every object touched. But how do I know which sprite has been swiped to write the code for applying impulse to that particular sprite?
I am trying the following code:
SKNode *sprite = [self nodeAtPoint:location];
[ball.physicsBody applyImpulse:CGVectorMake(dx, dy) atPoint:location];
[self addChild:sprite];
Also,
userInteractionEnabled = YES for all the sprites
And all the sprites are performing an action (Just in case this is the reason why I cannot swipe them while they are already running an action, in this case what else should I use to move the sprites?)
Sorry if this is too dumb, I am a noob
Thanks in advance!
You will need to use the name of the sprite with the name property:
node.name = #"nodeName";
for(SKNode *node in [self nodesAtPoint:location])
{
if([node.name isEqualToString:#"nodeName"])
{
// your custom code here
}
}
I hope this is what you were looking for, if not i am always here to help.

Pause and resume animation in the same keyframe

Is it possible to pause animation of SCNNode (animaton with model from .dae collada) and then resume in the same keyframe which it was paused?
Will using the isPaused property on the SCNNode work for your needs?
Example:
self.childNode.isPaused = true

SKView Flashing Gray before Scene

I have a main view of type UIView. This view has two skview's (left and right) in landscape only orientation. All views and scenes are set with a black background.
I start out with the two skviews hidden. The main screen shows questions on either side of the screen. If the answer is incorrect I set a scene to an effect and then enable that effect and unhide the skview (left or right). The effect is shown for several seconds after which I disable it with [self.leftView presentScene:nil]; I do the same with the rightView. I then hide the views again.
The issue is that when the scenes are shown there is a brief flash of the view in a white color before the scene is rendered appropriately with the black background. In fact this is why I took to hide the skviews to begin with as if I don't they will show with a lighter background despite my setting it to black.
How can I show these scenes without the flash of a lighter background color?
Some representative code:
self.fireSceneLeft = [FireScene sceneWithSize:self.leftView.bounds.size];
self.fireSceneLeft.scaleMode = SKSceneScaleModeAspectFill;
self.fireSceneLeft.backgroundColor = [UIColor blackColor];
[self.leftView presentScene:self.fireSceneLeft];
[self.leftView setHidden:NO];
As for the scene effect itself:
#implementation FireScene
-(SKEmitterNode *)fireEffect
{
SKEmitterNode *emitter = [NSKeyedUnarchiver unarchiveObjectWithFile:[[NSBundle mainBundle] pathForResource:#"FireEffect" ofType:#"sks"]];
emitter.position = CGPointMake(150,80);
emitter.name = #"fire";
emitter.targetNode = self.scene;
emitter.numParticlesToEmit = 2;
return emitter;
}
-(void)update:(CFTimeInterval)currentTime {
[self addChild:[self fireEffect]];
}
#end
I solved this issue by creating another scene that is simply black. Instead of setting the scene I want to move away from to nil, I simply substitute in the black scene. A scene with nothing on it (blank SKView) has a gray color which is the cause of my problem. By starting the app with the black scene and using it when no scene should display, my problem was solved. An important point here as well is pausing the scene. Even a black scene with no movement will use up CPU if not paused. I found the best place to pause the black scene was in the following method of the scene controller:
-(void)update:(CFTimeInterval)currentTime {
[self addChild:[self blackEffect]];
[self.view setPaused:YES];
}
This was also tricky because pausing the scene elsewhere actually paused the older scene. This is a timing problem because even if you call a new scene and then pause, it won't have had the time to get the new scene in place before the pause. The method above was the only place I could reliably call the pause and have it take effect on the correct scene.
On iOS you can't have 2 (or more) SKView instances at the same time. While it works technically and on first sight it is actually unusable because one view will dominate the other(s), leaving very little time for the other view(s) to update and render their contents as well as receiving touch and other events. I suspect the brief flash is related to this.

Add Action on CCLayer in cocos2d iOS

I have a CCLayer class which i'm using for pause menu and inside that class i have menuitems . I've just added menu and it shows on screen but no animation in it. I want to add transition effect on layer as we can do it in scene. or add action as we do in sprite. I just want my pause menu to animate from up to down.
Here how i am adding my CClayer class.
menuLayer = [[PauseMenu alloc] initWithParent:self];
[self addChild:menuLayer z:99];
I have tried this code for action but it doesn't work
menuLayer = [[PauseMenu alloc] initWithParent:self];
[self addChild:menuLayer z:99];
id move=[CCMoveTo actionWithDuration:5.1 position:ccp(240,120)];
[menuLayer runAction:move];
Following your comment I'll recommend you not to use [[CCDirector sharedDirector] pause] as it does not really will pause your game logic (only actions and schedulers) but if you have some thread doing game logic (like moving objects or calculating some stuff) it will still keep running.
If you want to pause your game you should keep an internal state of your game. So for example in your update method you could do :
if (gameState == GAME_PAUSE)
return;
This way it will be easy for you to decide what continues to be done and what not until the game returns to play.

Resources