cocos2d 2.0-rc2: finaliza el director y reinicia

Tengo un juego de cocos2d que utiliza menus UIKit, por lo que solo utilizo el framework para un viewcontroller, que es el juego en sí. Además, solo tiene una escena. Desde cocos2d 2.0, el director en sí mismo es una subclass UIViewController , así que simplemente lo MenuViewController en mi MenuViewController cuando el usuario toca un button de inicio:

 -(void)startGameButtonPressed { CCDirectorIOS* director = (CCDirectorIOS *) [CCDirector shanetworkingDirector]; // 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 shanetworkingApplication] delegate]]; [self.navigationController pushViewController:director animated:YES]; } 

Esto funciona bien por primera vez que se llama al método, cuando el usuario inicia el primer juego. Cuando termina el juego, [[CCDirector shanetworkingDirector] end] .

La mayor parte de la configuration del director se realiza en appDelegate (se toma sin cambios desde la plantilla pnetworkingeterminada de Cocos2d). Solo puse CCGLView como una propiedad retenida en mi MenuViewController , porque de lo contrario la aplicación falla cuando se [[CCDirector shanetworkingDirector] end] y CCGLView no se retiene. Creo que podría ser un error de cocos2d. En [[CCDirector shanetworkingDirector] end] el marco llama [self setView:nil] , pero aún intenta acceder a la vista más adelante (probablemente en otro subprocess).

El problema ahora es que en la segunda llamada de mi método anterior (cuando el usuario quiere comenzar otro juego desde el menu), startGameButtonPressed , el director se empuja pero la pantalla permanece negra. El juego se está ejecutando y respondiendo, simplemente no veo nada. ¿Alguien puede ayudarme con eso?

Bien, tuve el mismo problema y pude "arreglarlo".

Cuando configura CCGLView y [director setView:], incluso si activa el controller, la escena aún existe. lo único que sucede es que la escena se detiene.

Por lo tanto, para que el "reinicio" funcione, debe comprobar si ya existe una escena en ejecución (incluso si está detenido, y en lugar de runWithScene: use replaceScene:

Aquí está mi código para que pueda ver:

 - (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 shanetworkingApplication] 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]]; } 

Espero que este código te ayude, porque pasé todo un día tratando de resolver esto. Puede que no sea la forma correcta o incluso la más bonita, pero está funcionando 🙂

EDIT: Además, por favor, no que si POP la escena COCOS2D, no tiene que [[CCDirector shanetworkingDirector] end] ya que la animation se detendrá cuando la vista se elimine / se elimine.

He pasado varios días buscando información relacionada con esto, y compartiré con ustedes mi propia experiencia. También estoy tratando de crear un juego que se carga en un UITableViewController, desde el que se carga el CCDirector cuando se toca una celda. Este es un juego basado en turnos Game Center, de ahí el layout (piense en Words With Friends). El mejor enfoque que he encontrado hasta ahora para esto es el siguiente (tenga en count que estoy trabajando en 2.0, donde CCDirector es una subclass UIViewController):

En AppDelegate.h, cree un ivar nuevo para contener CCGLView que se crea a partir del código de plantilla. Luego, asigna CCGLView creado en didFinishLaunching a tu nuevo ivar. Esto permite que el director reutilice la vista creada originalmente en lugar de tratar de volver a crearla cada vez que recargue el CCDirector, lo que parece causar todo tipo de problemas extraños en mi experiencia.

También quiere crear un nuevo método en AppDelegate llamado -setupDirector o algo similar donde usted, bien, configurará el director. Esto debería llamarse cada vez que recrea el CCDirector. He publicado mi versión a continuación. Tenga en count que mi ivar para CCGLView se llama "GLView".

 - (void)setupDirector { if (![CCDirector shanetworkingDirector]) { CCLOG(@"Calling setupDirector"); director_ = (CCDirectorIOS*) [CCDirector shanetworkingDirector]; 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 *shanetworkingFileUtils = [CCFileUtils shanetworkingFileUtils]; [shanetworkingFileUtils setEnableFallbackSuffixes:NO]; // Default: NO. No fallback suffixes are going to be used [shanetworkingFileUtils setiPhoneRetinaDisplaySuffix:@"-hd"]; // Default on iPhone RetinaDisplay is "-hd" [shanetworkingFileUtils setiPadSuffix:@"-ipad"]; // Default on iPad is "ipad" [shanetworkingFileUtils setiPadRetinaDisplaySuffix:@"-ipadhd"]; // Default on iPad RetinaDisplay is "-ipadhd" // Assume that PVR images have premultiplied alpha [CCTexture2D PVRImagesHavePremultipliedAlpha:YES]; } 

Además, querrá hacer un par de cambios en la forma en que la plantilla carga los controlleres de vista. Normalmente, cocos2D configura el controller de navigation con director_ como el controller de vista raíz. Aquí, quiere asignar e iniciar el controller de vista de menu y agregar THAT en lugar de director_:

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

Todo lo demás en didFinishLaunching puede seguir siendo el mismo. Ahora, en su menuViewController en su método startGameButtonPressed, llamará al método setupDirector recién creado en su instancia de la aplicación, al que se hace reference llamando a:

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

Incluyo una comprobación para asegurarme de que el CCDirector aún no se está ejecutando y, si es así, finalícelo. En tu capa de juego, cuando llegue el momento en que quieras abrir el controller de vista, simplemente lo llamarás así:

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

Este flujo debería permitirle utilizar libremente un controller de navigation para impulsar su escena del juego con CCDirector y hacer que aparezca el controller de vista cuando desee volver al menu principal basado en UIKit. Espero que esto ayude, ya que he pasado mucho time frustrante tratando de hacer esto correcto para mi propio juego.

Lo que funciona bien es simplemente llamar a startAnimation y stopAnimation en el director, pero mantener la vista de cocos2d alnetworkingedor y simplemente volver a usarla.

Cualquier bash de cerrar cocos2d y su vista OpenGL y volver a inicializarlo más adelante causará más o less problemas, porque realmente no se ha probado lo suficientemente bien. Aparte de que cocos2d funciona bien con UIKit, tiene los mismos problemas que cualquier otra aplicación OpenGL ES al mezclarlo con vistas UIKit.

En mi experiencia, Cocos realmente no es compatible con el final y la reanudación, actúa como si estuviera hecho y casi se apaga.

Hay dos cosas que puede probar, la primera (y me vino a la mente) es llamar a CC_DIRECTOR_INIT (puede no ser el nombre exacto) después de que el director terminó, y antes de que quiera comenzar de nuevo.

El segundo es editar el código fuente del director y modificar el método end para que deje los cocos en un estado utilizable (evitar que suelte la vista y purgar el caching, etc.). Alternativamente a esto, puede modificar el método de start para asegurarse de que Cocos esté en estado utilizable antes de comenzar.

Lamentablemente, Cocos no nos facilita el uso de UIKit + Cocos, pero con suerte.