1
votes

I have a Cocos2d game scene that loads with an EAGLView loaded by a UIViewController, but when I exit the game scene back to a UIKit Menu, my game scene is being deallocated in a weird way. I think if I made the game purely in Cocos2d without combining it with UIKit, this would not happen. If I call pause on CCDirector when UIViewController pops, I found that if I want to reenter the game scene, the UIViewController will load again, and simply resuming CCDirector will show a blank screen with an OpenGL error. If try [[CCDirector sharedDirector] runWithScene] it says I cannot do that if a scene is already running, but if I try replaceScene, it says that a dealloc message (for a CCSprite, no idea which one) is being sent to a deallocated instance. Here is some of my code:

- (void)viewDidLoad {
    [super viewDidLoad];
    glView = [EAGLView viewWithFrame:self.view.bounds
                         pixelFormat:kEAGLColorFormatRGB565 // kEAGLColorFormatRGBA8
                         depthFormat:0                        // GL_DEPTH_COMPONENT16_OES
              ];
    glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self.view insertSubview:glView atIndex:0];
    [[CCDirector sharedDirector] setOpenGLView:glView];

    if (![[CCDirector sharedDirector] runningScene]) {
        CCScene *scene = [GameLayer scene];
        [[CCDirector sharedDirector] runWithScene:scene];
    }
    else {
        [self.view insertSubview:[[CCDirector sharedDirector] openGLView] atIndex:0];
        [[CCDirector sharedDirector] resume];    // Pause is in viewWillDisappear

        // If I replace resume with below, I get message sent to deallocated instance
        [[CCDirector sharedDirector] replaceScene:scene];
    }
}

If I run it like this, I get EXC_BAD_ACCESS inside CCTextureAtlas in the line with glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*)(start*6*sizeof(indices_[0])));

If I run it without reinitializing the glview, only initializing the first time, like if (![[CCDirector sharedDirector]openGLView]) initialize, I get a blank screen and OpenGL error 0x0506 in -[EAGLView swapBuffers].

How would I either retain my scene without doing something too contorted, or cleanly release my scene so that I may reload it with [[CCDirected sharedDirector] runWithScene]?

2

2 Answers

1
votes

How do you "exit the scene"? This would be the more interesting code to have a look at.

Here's what I found strange about the code you posted:

- (void)viewDidLoad {
    … 

    if (![[CCDirector sharedDirector] runningScene]) {
        ...
    }
    else {
        // Where does this scene variable come from?
        [[CCDirector sharedDirector] replaceScene:scene];
    }
}

Normally when you run replaceScene you provide a new scene. It's possible that you try to replaceScene with the same scene that is also the currently running scene. This will certainly crash cocos2d. If you want the same scene to re-appear, either don't call replaceScene or create the scene anew.

You also will want to check that the currently running scene does not dealloc. Set a breakpoint in the dealloc method of the scene. If it deallocs you probably fell for the misconception that you have to wipe the cocos2d scene from memory. You should not do that, I believe cocos2d always expects there to be at least one running scene after you called runWithScene.

For what it's worth, you will want to use startAnimation and stopAnimation instead of pause and resume. This will entirely halt Cocos2D without releasing the scene, so it works the same as pause/resume. My guess is that internally it shuts down the game loop altogether whereas pause/resume keeps it running at a very slow rate, ie 4 fps if I remember correctly.

I've had cases where pause/resume would cause the "OpenGL error 0x0506 in -[EAGLView swapBuffers]" and startAnimation/stopAnimation would fix that.

1
votes

How ever you leave the sene call

[[CCDirector SharedDirector]end];

This will call a number of methods on the Director and enalbe you to re-enter the scene without problems.