Cómo llamar a un método en helloworldlayer.mm desde appdelegate.mm

I'm making my first iphone game using cocos2d and box2d. I just implemented a pause button. It brings up a pause menu on top of the game and pauses CCDirector. Pausing and unpausing works great as long as you stay in the app but there's a bug. If you minimize the app while it's paused and come back to it, the game is unpaused again but the pause menu is still in front of it. The reason appears to be that the applicationDidBecomeActive method in AppDelegate.mm looks as follows:

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [[CCDirector sharedDirector] resume];
}

I tried just changing "resume" to "pause", but then the game pauses on start in every instance.

So I assume the solution is to add code into this method to either remove the pause layer or (better) to pause the director and make sure the pause layer is in place, so the game auto-pauses in any case if a player goes away and comes back. Trouble is, I'm really new to objective-c and can't figure out how to create a public method in my helloworldlayer and call it from AppDelegate. Can anybody give me a quick explanation of how to do this? I tried the following:

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [[CCDirector sharedDirector] pause];
        [HelloWorldLayer pause];

}

And then added the following code to my HelloWorldLayer.mm:

+(void)pauseGame {
    _paused = YES;
    _pauseMenu.visible = YES;
    _pauseLayer.visible = YES;
    [[CCDirector sharedDirector] pause];    
}

But it gives me errors - it says "instance variable _paused accessed in class method", and a similar error for the other two lines of code.

How do I fix this? I tried making the three variables properties and synthesizing them but this didn't help. The red exclamation points were replaced with yellow triangles (with the same warnings). But the program still crashes at that point in the code.

Gracias por su ayuda!

-James

EDIT: Woo! I figured it out!

My problem was in not realizing that a + method applies to the class, not the instance, and therefore can't access variables of a specific instance. Since that's what I needed to do, I looked for a way to communicate between appDelegate and a specific Cocos2D layer. This tutorial proved supremely helpful:

http://www.cocos2d-iphone.org/forum/topic/9354

Here's the code I ended up using: In appDelegate.mm, I replaced the end of the applicationDidFinishLaunching method with the following lines:

// Run the intro Scene
CCLayer *layer = [HelloWorldLayer node]; //create and init layer
CCScene *scene = [CCScene node]; //create and init parent and empty scene
[scene addChild:layer z:0 tag:100]; //TAG EACH LAYER WITH A UNIQUE NUMBER!!!
[[CCDirector sharedDirector] runWithScene: scene];

Then I added the following to applicationDidResignActive:

- (void)applicationWillResignActive:(UIApplication *)application {
    [[CCDirector sharedDirector] pause];
    CCScene * scene = [[CCDirector sharedDirector] runningScene];
    id layer = [scene getChildByTag:100];
    [layer pauseGame];
}

And I removed the default unpause functionality from applicationDidBecomeActive, since I want it to stay paused and have loaded the pause screen.

Finally, in HelloWorldLayer.mm I restored the function to what it was originally:

-(void)pauseGame {
    _paused = YES;
    _pauseMenu.visible = YES;
    _pauseLayer.visible = YES;
    [[CCDirector sharedDirector] pause];
}

Note that I changed it back to an instance method and all the variables are instance variables again.

Thanks for your response, ZhangChin, it set me on the course to figuring this out. Hope this helps somebody in the future :-) -James

preguntado el 01 de febrero de 12 a las 04:02

1 Respuestas

You need +pauseGame like this:

+(void)pauseGame {
    CCDirector *sharedDirector = [CCDirector sharedDirector];

    sharedDirector.paused = NO;
    sharedDirector.pauseMenu.visible = NO;
    sharedDirector.pauseLayer.visible = NO;
    [sharedDirector resume];    
}

Also, you may need to @synthesize or write setter methods for those properties.

Respondido 01 Feb 12, 08:02

Thanks! I tried the code you sent and it didn't work but your response was still quite helpful. The properties paused, pausemenu and pauselayer are properties of HelloWorldLayer, not the director, so the next thing I tried was the following: - James

+(void)pauseGame { HelloWorldLayer *layer = [HelloWorldLayer node]; layer.paused = YES; layer.pauseMenu.visible = YES; layer.pauseLayer.visible = YES; [[CCDirector sharedDirector] pause]; } This gave no errors, but it didn't actually work, I think because I created a new instance of HelloWorldLayer and modified its variables. How do I refer to the existing instance here? - James

man, these comments screwed up all my formatting. Forgive me, I'm new to stack overflow. Should I have put these as a new answer? - James

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.