Pause button in SpriteKit takes several taps to resume the game - sprite-kit

I have read several questions/answers posted about pausing a scene in SpriteKit but none solve the issue I’m having.
I have a pause button on my game scene. The Z position is much higher than any other SKSpriteNode in the scene. The first problem is that sometimes it takes 2 or 3 taps to pause the scene but the MAIN problem is that to resume the game, sometimes it works as it should with just one tap but some other times, tapping on it advances 2 - 3 frames and I have to tap sometimes even 5 times for the game to fully resume.
Below is the code I’m using for my pause button and it is inside my touchesMoved function using Swift 3. Could you guys offer any suggestions to improve this code and fix this glitch? Thanks for your help.
let nodeUserTapped = atPoint(pointOfTouch)
if nodeUserTapped.name == "PauseButton" {
if (self.isPaused == true) {
self.isPaused = false
physicsWorld.speed = 1
} else {
self.isPaused = true
physicsWorld.speed = 0
}
}

Usually you should use touchesBegan simply to animate the button with a "pressed button" texture, then put your code in touchesEnded to be sure to run it when the user release the finger inside the button. The code you've written in touchesMoved is run only when the finger slide at least a little bit on the screen.

Related

Is CCScene replace during CCTransition possible?

Calling replaceScene: with a CCScene on CCDirector which is during a CCTransition results in dealloc not being called on any scene used, moreover, after this operation any scene is not being displayed.
Here is a link to the sample project
Shortest way to obtain this behavior is such method (I mean reproducing the problem):
SceneOne *destScene = [SceneOne node];
CCTransitionFade *transition = [[CCTransitionFade alloc]initWithDuration:2 scene:destScene];
[[CCDirector sharedDirector]replaceScene:transition];
double delayInSeconds = 1.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[[CCDirector sharedDirector]replaceScene:[SceneTwo node]];
});
My question is: is there any feasible way to replace scenes when the CCTransition is being performed by the CCDirector?
I have implemented a delegate callback from CCDirector informing me about ending scene replacement, but this is never called if I push the iPhone home button during CCTransition.
If the answer is no, is there a cocos2d-iphone way to achieve goal described below?
Originally, this problem arised when I wanted to add "loading scene" when applicationDidEnterBackground (as a background task) or applicationWillEnterForeground, but I realized it has nothing to do with background execution. My ultimate goal is to provide seamless user experience while a game is waiting for Game Center authentication handler being called, and a "loading scene" being displayed from the very start of the app awaked from background would be sufficient (not only preventing user interaction which can be done many ways, but not showing previous game UI to the user). However, this solution is susceptible to the problem described above - if user taps the home button during scene transition he is going to get a very strange screen after bringing the game from background.
EDIT: After some more research I didn't find any satisfactory solution to replacing scene during CCTransition, however, problem described above was solved by not calling replaceScene but by adding a "loading" CCLayer to the visible CCScene, as #LearnCocos2D (thanks Steffen) suggested. This is not perfect, since adding a child during scene transition still has some narrow window (in the sense of running time) when strange results occur, but it is much better than replacing the scene. I would like to mention that it only concerns me when testing my game on 3GS, since newer devices are significantly faster and it is very difficult to reproduce the problem of "home button" clicking during CCTransition on something faster than 3GS.

ignore touch events

I´m making a game with cocos2d and need to ignore touch events in some cases, esp. when another touch is "in progress".
It is, the player touches the screen, moves the finger around and then ends the touch. During this period, I need to ignore all other touches that may occur. How can I do that?
self.userInteractionEnabled = YES;

Cocos2d access scene properties and methods

I'm trying to include a pause feature for my game. So far running pause on the [CCDirector sharedDirector] has been good enough when run through my pauseGame method (which incorporates a BOOL to tell if game is paused, etc.)
However, I noticed that if I go back to the homescreen on my device, my application delegate will automatically run pause and resume on the sharedDirector.
Ideally, I would like access my active scene/layer's so I can run my own pause method.
How can I: 1) check if the current scene is my game scene
2) access the game scene's pause property, and run the pauseGame method on it?
Any help appreciated. Thanks
The running scene is [CCDirector sharedDirector].runningScene
If you call [scene pauseSchedulerAndActions]; on the current scene this is will not be resumed when going back and forth on the home screen.
If you need to pause ALL nodes in the hierarchy, here is a method to extend CCNode
-(void)recursivePauseSchedulerAndActions {
[self pauseSchedulerAndActions];
CCNode *child;
CCARRAY_FOREACH(children_, child) {
[child recursivePauseSchedulerAndActions];
}
}
-(void)recursiveResumeSchedulerAndActions {
[self resumeSchedulerAndActions];
CCNode *child;
CCARRAY_FOREACH(children_, child) {
[child recursiveResumeSchedulerAndActions];
}
}
I use a different approach for pausing a game.
I usually have a game scene with game layers. To pause the game I add a new layer (covering the entire screen) and when I pause the game I display this layer. This way you can stop touching events for the game layer and restore them when resuming the game (and removing the pause layer from the scene)

iPhone: Button Touch Events - Release not Firing?

SOLVED - Please seen Darren's response for a working resolution to this issue.
Hello, and thank you for taking the time to read my question.
I am experiencing some odd behavior with detecting the release of an IBAction UIButton: When I move my palm across the interface, button press is detected, however release is not!
I have a set of controls, each with their own IBAction UIButton. Here is an example of how my buttons react and behave:
- (IBAction)up1start:(id)sender
{
if(!buttonIsPressed && deviceIsConnected)
{
NSLog(#"BUTTON UP 1 PRESSED!");
NSString *byteString = #"7E 01";
sendTimer =[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(sendByte:) userInfo:byteString repeats:YES];
buttonIsPressed = true;
}else{
NSLog(#"Cant press two buttons or connection is closed");
}
}
- (IBAction)up1stop:(id)sender
{
NSLog(#"BUTTON UP 1 RELEASED!");
[ self buttonRelease ];
}
I have the following events attached to UIButton up1 - likely more than necessary due to my ongoing troubleshooting efforts:
Touch Down - up1start
Touch Drag Exit - up1stop
Touch Drag Outside - up1stop
Touch Up Inside - up1stop
Touch Up Outside - up1stop
I'm a bit stumped here as to how none of these events result in my "up1stop" action being triggered. Again, I can reproduce this issue by pressing my palm against the interface and then releasing, or moving slightly. For the record, I have enabled exclusiveTouch for each button.
Everything else is working perfectly and I DO have to try to get this behavior to occur, however given the nature of the app it would be incredibly unsafe for users if this is not resolved.
Can anyone explain why the button release is not being detected when I 'palm' the screen?
Cheers!
You'll want to track the UIControlEventTouchCancel event.
A UIControlEventTouchCancel event occurs if the initial touch in reinterpreted as another gesture, such as a scroll.

Why is detecting touches getting slower and slower?

In my game if I play a particular game for several times, my touches need more time to be detected.
It stores all touches and then applies those touches all at the same time.
Can anybody tell me what's the problem?
In touchesBegan I wrote:
if (CGRectContainsPoint([tapView frame], [touch locationInView:self])
&& tapView.alpha == 1) {
[self callTapCode];
}
This is the code of touchesEnded. If I tapped and release the tapped it shows one tapping event.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (checkTap == TRUE && tapView.alpha == 1 )
tap_effect_view.alpha = 0;
}
- (void)callTapCode {
// Move player code by 6 pixels
// not possible to write all code
}
In tapView I continuously tap. callTapCode moves the player by six pixels. But after some time my touches detected very slowly, so that the player looks like he's jumping around. I played the game continuously 15 to 16 times.
You might work through this tutorial to learn how to use the Leaks Instrument. This is part of the Instruments suite that comes with Xcode, which will, among other things, help you track down memory leaks and general performance issues with your application.
I found the solution to my problem. In my game I had enabled the tapView.multipleTouchEnabled = TRUE
tapView is the view where I was continuously tapping.
When I make it FALSE it works.
i.e.
tapView.multipleTouchEnabled = FALSE;
I exactly dont know how. But it works.
Thanks for the replies.
Try to look for any memory leaks. Maybe the iPhone has to use virtual memory a lot.