Cocos2d 2.0-rc2: shut down the director and restart

I have a game with cocos2d that uses a UIKit menu, so I only use the framework for one viewcontroller, which is the game itself. In addition, he has only one scene. Since cocos2d 2.0 is itself a subclass of the UIViewController , so I just click it on the MenuViewController when the user clicks the start button:

 -(void)startGameButtonPressed { CCDirectorIOS* director = (CCDirectorIOS *) [CCDirector sharedDirector]; // Create an CCGLView with a RGB565 color buffer, and a depth buffer of 0-bits self.glView = [CCGLView viewWithFrame:CGRectMake(0, 0, 480, 320) pixelFormat:kEAGLColorFormatRGB565 //kEAGLColorFormatRGBA8 depthFormat:0 //GL_DEPTH_COMPONENT24_OES preserveBackbuffer:NO sharegroup:nil multiSampling:NO numberOfSamples:0]; // attach the openglView to the director [director setView:glView]; [director runWithScene:[GameLayer scene]]; [director setDelegate:(id <CCDirectorDelegate>) [[UIApplication sharedApplication] delegate]]; [self.navigationController pushViewController:director animated:YES]; } 

This works great the first time the method is called, when the user launches the first game. When the game is finished, I call [[CCDirector sharedDirector] end] .

Most of the director’s settings are made in appDelegate (it does not change from the Cocos2d template by default). I put CCGLView as a persistent property in my MenuViewController , because otherwise the application crashes when [[CCDirector sharedDirector] end] is CCGLView , and CCGLView not saved. I think it might be a cocos2d error. At the [[CCDirector sharedDirector] end] framework calls [self setView:nil] , but it still tries to access the view later (possibly in a different thread).

The problem is that the second time I call my method above (when the user wants to start another game from the menu), startGameButtonPressed , the director receives a click, but the screen remains black. The game works and responds, I just don’t see anything. Can someone please help me with this?

+7
source share
4 answers

OK, I had the same problem and I was able to “fix” it.

When you install CCGLView and [Director setView:], even if you pull out the controller, the scene still exists. what happens is that the scene stops.

So, in order for the "reboot" to work, you must check if the scene is already running (even if it is stopped, and runWithScene: used instead of runWithScene:

Here is my code so you can see:

 - (void)setupCocos2D { CCGLView *glView = [CCGLView viewWithFrame:CGRectMake(0, 0, 320, 480) pixelFormat:kEAGLColorFormatRGB565 //kEAGLColorFormatRGBA8 depthFormat:0 //GL_DEPTH_COMPONENT24_OES preserveBackbuffer:NO sharegroup:nil multiSampling:NO numberOfSamples:0]; // HERE YOU CHECK TO SEE IF THERE IS A SCENE RUNNING IN THE DIRECTOR ALREADY if(![director_ runningScene]){ [director_ setView:glView]; // SET THE DIRECTOR VIEW if( ! [director_ enableRetinaDisplay:YES] ) // ENABLE RETINA CCLOG(@"Retina Display Not supported"); [director_ runWithScene:[HelloWorldLayer scene]]; // RUN THE SCENE } else { // THERE IS A SCENE, START SINCE IT WAS STOPPED AND REPLACE TO RESTART [director_ startAnimation]; [director_ replaceScene:[HelloWorldLayer scene]]; } [director_ setDelegate:(id <CCDirectorDelegate>) [[UIApplication sharedApplication] delegate]]; // I DO NOT PUSH BECAUSE I ALREADY PUSHED TO THIS CONTROLLER, SO I ADD THE COCOS2D VIEW AS A SUBVIEW [self.view addSubview:[director_ view]]; } 

Hope this code helps you because all day I tried to figure it out. It may not be the right way or even the most beautiful way, but it works :)

EDIT: Also, please do not follow that if you are POP the COCOS2D scene, you do not need [[CCDirector sharedDirector] end] , because the animation will stop when the view is deleted or deleted.

+8
source

I spent several days searching for information related to this and will share my experience with you. I am also trying to create a game loaded in a UITableViewController from which a CCD file is loaded when the cell is touched. This is the game center of a turn-based game, therefore, design (think words with friends). The best approach I have found so far for this is as follows (note that I work in 2.0 - where CCDirector is a subclass of UIViewController):

In AppDelegate.h, create a new ivar to store the CCGLView that is created from the template code. Then assign the CCGLView created in the didFinishLaunching file to your new ivar. This allows the director to reuse the original created view instead of trying to recreate it every time you reboot the CCDirector, which seems to cause me all kinds of strange problems.

You also want to create a new method in AppDelegate called -setupDirector, or something like where you, well, set up the director. This must be called up every time you recreate the CCDirector. I posted my version below. Please note that my ivar for CCGLView is called "GLView".

 - (void)setupDirector { if (![CCDirector sharedDirector]) { CCLOG(@"Calling setupDirector"); director_ = (CCDirectorIOS*) [CCDirector sharedDirector]; director_.wantsFullScreenLayout = YES; // Display FSP and SPF [director_ setDisplayStats:NO]; // set FPS at 60 [director_ setAnimationInterval:1.0/60]; // attach the openglView to the director [director_ setView:GLView]; // for rotation and other messages [director_ setDelegate:self]; // 2D projection [director_ setProjection:kCCDirectorProjection2D]; // [director setProjection:kCCDirectorProjection3D]; // Enables High Res mode (Retina Display) on iPhone 4 and maintains low res on all other devices if( ! [director_ enableRetinaDisplay:YES] ) CCLOG(@"Retina Display Not supported"); // Default texture format for PNG/BMP/TIFF/JPEG/GIF images // It can be RGBA8888, RGBA4444, RGB5_A1, RGB565 // You can change anytime. [CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888]; // If the 1st suffix is not found and if fallback is enabled then fallback suffixes are going to searched. If none is found, it will try with the name without suffix. // On iPad HD : "-ipadhd", "-ipad", "-hd" // On iPad : "-ipad", "-hd" // On iPhone HD: "-hd" CCFileUtils *sharedFileUtils = [CCFileUtils sharedFileUtils]; [sharedFileUtils setEnableFallbackSuffixes:NO]; // Default: NO. No fallback suffixes are going to be used [sharedFileUtils setiPhoneRetinaDisplaySuffix:@"-hd"]; // Default on iPhone RetinaDisplay is "-hd" [sharedFileUtils setiPadSuffix:@"-ipad"]; // Default on iPad is "ipad" [sharedFileUtils setiPadRetinaDisplaySuffix:@"-ipadhd"]; // Default on iPad RetinaDisplay is "-ipadhd" // Assume that PVR images have premultiplied alpha [CCTexture2D PVRImagesHavePremultipliedAlpha:YES]; } 

In addition, you will want to make a couple of changes to the way the controllers load the template. Typically, cocos2D installs a navigation controller with director_ as the root view controller. Here you want to select and initialize your menu controller and add TO instead of director _:

 // Create a Navigation Controller with the Director gamesTVC_ = [[GamesTableViewController alloc] initWithStyle:UITableViewStyleGrouped]; navController_ = [[UINavigationController alloc] initWithRootViewController:gamesTVC_]; navController_.navigationBarHidden = NO; 

Everything else in didFinishLaunching can stay the same. Now, in your menuViewController in your startGameButtonPressed method, you will call the newly created setupDirector method in your application, which is invoked by the call:

 AppController *app = (AppController *)[[UIApplication sharedApplication] delegate]; if ([CCDirector sharedDirector].runningScene) { [[CCDirectorIOS sharedDirector] end]; } [app setupDirector]; [app.navController pushViewController:app.director animated:YES]; 

I turn on verification to make sure that the CCD file is not already running, and if so, complete it. In the game layer, when the time comes when you want to set the view controller, you simply name it like this:

 AppController *app = (AppController *)[[UIApplication sharedApplication] delegate]; [app.navController popViewControllerAnimated:YES]; [[CCDirector sharedDirector] end]; 

This stream should allow you to freely use the navigation controller to promote your game scene using CCDirector and call this view controller when you want to return to the main menu based on UIKit. Hope this helps, since I spent a lot of disappointing time trying to get this right for my own game.

+5
source

What works well is simply to call startAnimation and stopAnimation in the director, but leave cocos2d to look up and just reuse it.

Any attempts to close cocos2d and view it with OpenGL and reinitialize it later will cause more or less problems, because it is really not sufficiently tested. Besides the fact that cocos2d works great with UIKit, it has the same problems as any other OpenGL ES application when mixing with UIKit views.

+2
source

In my experience, Cocos does not actually support ending and resuming, it acts as if it were done, and pretty much closes.

There are two things you can try: the first one (and it occurred to me) is to call CC_DIRECTOR_INIT (it may not be the exact name) after the director has finished and before you want to start it again.

The second is to edit the director’s source code and change the end method to leave the coconuts operational (stop it from releasing and clearing the cache, etc.). Alternatively, you can modify the start method to make sure Cocos is in a usable state before starting.

Unfortunately, Cocos does not allow us to use UIKit + Cocos, but with good luck with it.

0
source

All Articles