2012-06-14 6 views
7

Tengo un juego impulsado por cocos2d que usa menús UIKit, así que solo uso 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í es una subclase UIViewController, por lo que sólo empujar en mi MenuViewController cuando el usuario pulsa un botón de inicio:cocos2d 2.0-rc2: finaliza el director y reinícialo

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

Esto funciona muy bien para la primera vez que el método se llama, cuando el usuario inicia el primer juego Cuando el juego termina, llamo al [[CCDirector sharedDirector] end].

La mayor parte de la configuración del director se realiza en la aplicaciónDelegate (se toma sin cambios de la plantilla predeterminada de Cocos2d). Solo puse el CCGLView como propiedad retenida en mi MenuViewController, porque de lo contrario la aplicación se bloquea cuando se llama a [[CCDirector sharedDirector] end] y no se conserva el CCGLView. Creo que podría ser un error de cocos2d. En [[CCDirector sharedDirector] end], el marco llama al [self setView:nil], pero todavía intenta acceder a la vista más adelante (probablemente en otro hilo).

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

+0

Realmente podría usar una respuesta a esta pregunta. Es el quid de mi aplicación en este momento. – Echilon

Respuesta

8

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

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

Para que el "reinicio" funcione, debe verificar si ya hay una escena en ejecución (incluso si está detenida, y en lugar de runWithScene: usa 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 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]]; 

} 

Esperanza este código le ayudará, porque pasé un día entero tratando de resolver esto. puede que no sea la forma correcta o incluso la forma más bonita, pero está trabajando :)

EDIT: También, por favor, no que si usted POP Cocos2d la escena, que no tienen que [[CCDirector sharedDirector] end] como la animación se detendrá cuando la vista se destrabe/elimine.

+0

Creo que la razón por la que esto funciona es que no empuja al director como un controlador de visualización, sino que más bien conecta el GLView a su propia vista. Sin embargo, ese podría ser un mejor enfoque que el mío. – avf

+0

Agradecimiento masivo por esta publicación @gmogames. Pasé horas luchando con esto. – Echilon

+0

Bien dicho ... Gracias por su valiosa respuesta ... –

0

En mi experiencia, Cocos realmente no admite el final y la reanudación, actúa como si estuviera hecho y prácticamente se apaga.

Hay dos cosas que puedes probar, la primera (y me vino a la mente) es llamar al CC_DIRECTOR_INIT (puede no ser el nombre exacto) después de que el director finalizó, y antes de que quieras volver a iniciarlo.

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 (evite que se libere la vista y purgue el caché, etc.). De forma alternativa a esto, puede modificar el método 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 un poco de suerte.

2

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

Cualquier intento de cerrar cocos2d y su vista OpenGL y reiniciarlo más adelante causará más o menos problemas, porque realmente no se ha probado lo suficiente. Aparte de que cocos2d funciona bien con UIKit, solo tiene los mismos problemas que cualquier otra aplicación OpenGL ES al mezclarlo con vistas de UIKit.

+0

El problema con ese enfoque es que todo el juego todavía está en la memoria. Además, he intentado hacer estallar la escena actual (la última en la pila), pero tiene los mismos problemas. Creo que este es un campo en el que cocos2d tiene que mejorar significativamente, ya que no parece ser un problema de OpenGL, sino más un problema de que el director no puede configurar correctamente el GLView después de terminar una vez. – avf

5

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

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

También desea crear un nuevo método en AppDelegate llamado -setupDirector o algo por el estilo donde, bueno, configure el director. Debe invocarse cada vez que esté recreando el CCDirector. He publicado mi versión a continuación. Tenga en cuenta que mi ivar para el CCGLView se llama "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]; 
} 

Además, querrá hacer un par de cambios en la forma en que la plantilla carga los controladores de visualización. Normalmente, cocos2D configura el controlador de navegación con director_ como controlador de vista raíz. A continuación, desea alloc e init su controlador de vista del menú y añadir que 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, se llama al método setupDirector recién creado en la instancia de aplicación, que se cita llamando al:

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

que incluyen una comprobación para asegurarse de que el CCDirector no sigue funcionando , y si lo es, finalícelo. En su capa de juego, cuando llegue el momento que desea pop el controlador de vista, simplemente llamarlo así:

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

Este flujo debe permitirle utilizar libremente un controlador de navegación para empujar a su escena del juego con CCDirector, y abre ese controlador de vista cuando quieras volver al menú principal basado en UIKit. Espero que esto ayude, ya que he pasado mucho tiempo frustrante tratando de hacer esto bien para mi propio juego.