I have a serious problem with Cocos2d.
1) I have one scene with few buttons in it
2) I have another scene in which i use
-(void) onEnter {
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowTouches:YES];
[super onEnter];
}
and also
-(void) onExit {
[[[CCDirector sharedDirector] touchDispatcher] removeDelegate:self];
[super onExit];
}
3) After replacing 1st scene to the 2nd everything is ok
4) But after returing to 1st scene (by replaceScene) all buttons on 1st scene are blocked. Nothing works
5) If i'm not using "removeDelegate" in "onExit()" buttons on 1st scene work, but touches from the 2nd scene are still active.
Related
Currently I'm fixing an old Cocos2D game. There is a strange problem with it: when the application is being sent to background by the four-finger gesture(iPad) after returning it behaves like the touch began and didn't end, and there no way to end it because the application does not respond to touches. Also when I launch the application and do nothing, the screen becomes locked and after that the application some times does not respond to touches.
I guess that there is something I need to do in the following AppDelegate methods, but I can't figure out exactly:
- (void)applicationWillResignActive:(UIApplication *)application {
[[CCDirector sharedDirector] pause];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[CCDirector sharedDirector] resume];
}
enter code here
- (void)applicationDidEnterBackground:(UIApplication*)application {
[[CCDirector sharedDirector] stopAnimation];
}
-(void) applicationWillEnterForeground:(UIApplication*)application {
[[CCDirector sharedDirector] startAnimation];
}
In parent view, there's a CCButton called pausebutton, when click it, a child view will be added to this view
[[CCDirector sharedDirector] pause];
pausebutton.selected = YES;
pauseLayer *pauseLayer = [pauseLayer node];
[self addChild:pauseLayer];
in child view pauseLayer, also has a ccbutton called resumebutton, when click it, this child view will be removed from parent view, and both set the pausebutton's selected is NO.
- (void)backResume:(id)sender
{
[self.parent removeChild:self cleanup:YES];
[[CCDirector sharedDirector] resume];
}
but i can't find a way to call the pausebutton from child view, so can you help me?
On the parent class, add a method to force a pause :
in .h :
-(void) forcePause;
in .m :
-(void) onButton:(id) sender {
[self forcePause];
}
-(void) forcePause {
[[CCDirector sharedDirector] pause];
pauseLayer *pauseLayer = [pauseLayer node];
[self addChild:pauseLayer];
}
and in the child, when the condition to trigger a pause is met
[self.parent forcePause];
just the general idea, there are other ways to make this happen. This example would be for a very simple use-case/game. Alternately, in the parent you could be listening for a #"forcePause" notification and notify in the child.
I am developing a cocos2d game where I have a CCLayer named GamePlaylayer and another CCLayer named ShopLayer. ShopLayer is a fullscreen layer. GamePlayLayer is touchenabled and has multiple buttons (CCMenuItemImage). ShopLayer is accessed from a shop button which has the following #selector.
(void) onClickShop {
ShopLayer * shop = [[ShopLayer alloc] init];
[self addChild:shop z:40]; }
To stop touch propagation I used CCTouchOneByOneDelegate and the following methods in the ShopLayer.
(void) onEnter {
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self
priority:0 swallowsTouches:YES];
[super onEnter];
}
(void) onExit {
[[[CCDirector sharedDirector] touchDispatcher] removeDelegate:self];
[super onExit];
}
(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
return YES;
}
Now it stops ccTouchesBegan of the GamePlayLayer to be called which is fine. But it cannot stop other buttons of the GamePlayLayer to be called. So when I touch at positions where the buttons of GamePlayLayer are placed, they get called even though I can not see them.
So my question is how to stop clicking buttons of lower layer from upper layer?
use kCCMenuHandlerPriority for the touch priority
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:kCCMenuHandlerPriority swallowsTouches:YES];
SetTouch priority kCCMenuHandlerPriority of this class.
I am trying to figure out touch handling on multiple CCNodes .
I have
Main CCLayer
------> z:2 Hud CCNode
On main layer I choose an object, on hud layer I want to control it. I followed this q&a its very helpful Cocos2d handling touch with multiple layers
On Main Layer touch events, below is Hud Node work:
-(void) registerWithTouchDispatcher
{
[[CCDirector sharedDirector].touchDispatcher addTargetedDelegate:self priority:0 swallowsTouches:YES];
}
-(BOOL) ccTouchBegan:(UITouch*)touch withEvent:(UIEvent*)event
{
//detects touched Object and sends it to hud
if (object != nil)
{
//sends it to hud
return true;
}
return false;
}
-(void) ccTouchMoved:(UITouch*)touch withEvent:(UIEvent*)event
-(void) ccTouchEnded:(UITouch*)touch withEvent:(UIEvent*)event
-(void) ccTouchCancelled:(UITouch*)touch withEvent:(UIEvent*)event
On Hud CCNode none of ccTouchBegan/moved/ended methods are fired
-(void) registerWithTouchDispatcher
{
[[CCDirector sharedDirector].touchDispatcher addTargetedDelegate:self priority:0 swallowsTouches:YES];
}
-(BOOL) ccTouchBegan:(UITouch*)touch withEvent:(UIEvent*)event
{
if (object!=nil) {
NSLog(#"Touch began");
return YES;
}
else
return NO;
}
EDIT:
I have a button to set speed of the object on HUD Node , it has nothing to do with object!=nil because when I put breakpoints I see that -(BOOL) ccTouchBegan:(UITouch*)touch withEvent:(UIEvent*)event is never called
-(void)speed1Tapped:(id)sender
{
if (object!=nil) {
NSLog(#"Moving Object is %#:",object!=nil);
}
}
On Log I get:
object is <ObjectATC: 0x13763850>
Why ccTouchBegan/moved/ended methods are not fired in CCNode?
How can I handle touches on multiple CCNodes, CCLayers ?
I guess you dont receive touch method because you did not register the touchDipatcher
either in your CCNodes init method or onEnter method try to register it.
//register touches
- (void)onEnter {
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
[super onEnter];
}
- (void)onExit {
[[[CCDirector sharedDirector] touchDispatcher]removeDelegate:self];
[super onExit];
}
In your touch methods, you have a conditional that says if (object != nil), but object is not defined anywhere in the code that you have shown. Is it defined elsewhere? Otherwise, this is why it is not firing.
Currently I have this code in my UIViewController:
//Cocos2D methods
-(id) init {
if((self=[super init]))
{
CCScene *scene = [CCScene node];
CCLayer *layer = [CCLayer node];
[scene addChild:layer];
[[CCDirector sharedDirector] runWithScene:scene];
[[CCDirector sharedDirector] setDisplayFPS:NO];
[self performSelector:#selector(cocosgameLoop:) withObject:nil afterDelay:1/60.0f];
}
return self;
}
- (void)cocosgameLoop:(ccTime)dT {
//Check for collisions here and add gravity, etc....
}
- (void)viewDidUnload {
[super viewDidUnload];
[[CCDirector sharedDirector] end];
}
//
My view controller is somewhat Objective-C code, but I want to add Cocos2D to the UIView. I think the code above is initializing it, but I am not sure. Also should the CCScene have its own class dedicated to everything that goes on in the scene? if so how would I do that?
I know these are a lot of questions, but my game is very similar to Doodle Jump and I need to know where to go from the current state I am in.
Does anyone have any ideas/tips?
Thanks!
performSelector will call the cocosgameLoop only once. You will want to call CCDirector startAnimation, and then schedule updates in your cocos2d nodes.
My Learn Cocos2D book (2nd Edition) explains how to add and setup Cocos2D in a UIKit view (regular iPhone) app.