2012-06-14 6 views
7
neu

Ich habe ein cocos2d-powered-Spiel, das UIKit-Menüs verwendet, also benutze ich nur das Framework für einen Viewcontroller, welches das Spiel selbst ist. Außerdem hat es nur eine Szene. Da cocos2d 2.0 der Regisseur selbst ist eine UIViewController Unterklasse, so schiebe ich es nur in meinem MenuViewController, wenn der Benutzer einen Startknopf tippt:cocos2d 2.0-rc2: Beende den Director und starte

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

Dies funktioniert zum ersten Mal wird das Verfahren, wenn der Benutzer beginnt genannt das erste Spiel. Wenn das Spiel vorbei ist, rufe ich [[CCDirector sharedDirector] end].

Die meisten Director-Setup ist in der AppDelegate erfolgt (es ist unverändert von der Standardvorlage Cocos2d übernommen). Ich habe nur die CCGLView als eine beibehaltene Eigenschaft in meine MenuViewController, weil sonst die App abstürzt, wenn [[CCDirector sharedDirector] end] aufgerufen wird und die CCGLView nicht beibehalten wird. Ich denke das könnte ein cocos2d Bug sein. In [[CCDirector sharedDirector] end] ruft das Framework [self setView:nil] auf, versucht jedoch später, auf die Ansicht zuzugreifen (wahrscheinlich in einem anderen Thread).

Das Problem ist jetzt, dass beim zweiten Aufruf meiner Methode oben (wenn der Benutzer ein anderes Spiel aus dem Menü starten möchte), startGameButtonPressed, der Regisseur wird gedrückt, aber der Bildschirm bleibt schwarz. Das Spiel läuft und reagiert, ich sehe nichts. Kann mir bitte jemand dabei helfen?

+0

Ich könnte wirklich eine Antwort auf diese Frage auch verwenden. Es ist der Kern meiner Anwendung gerade jetzt. – Echilon

Antwort

8

OK, ich hatte das gleiche Problem und ich konnte es "beheben".

Wenn Sie CCGLView und [director setView:] festlegen, bleibt die Szene selbst dann bestehen, wenn Sie den Controller öffnen. Das einzige, was passiert, ist, dass die Szene gestoppt wird.

Damit der "Neustart" funktioniert, müssen Sie überprüfen, ob bereits eine laufende Szene vorhanden ist (auch wenn sie gestoppt ist und statt runWithScene:replaceScene: verwenden.

Hier ist mein Code, so dass Sie sehen können:

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

} 

Hoffnung dieser Code wird Ihnen helfen, weil ich einen ganzen Tag damit verbracht, um dies herauszufinden. Es kann nicht der richtige Weg sein, oder sogar die schönste Art und Weise, aber es funktioniert :)

EDIT: bitte auch nicht, dass, wenn Sie die Cocos2D Szene POP, Sie haben nicht wie die Animation zu [[CCDirector sharedDirector] end] wird beendet, wenn die Ansicht freigegeben/entfernt wird.

+0

Ich denke der Grund, warum das funktioniert, ist, dass du den Director nicht als Viewcontroller drückst, sondern den GLView an eine eigene View angehängt hast. Das könnte ein besserer Ansatz sein als meiner. – avf

+0

Massiver Dank für diesen Beitrag @gmogames. Ich habe stundenlang damit gerungen. – Echilon

+0

Gut Said..Thanks für Ihre wertvolle Antwort ... –

0

Nach meiner Erfahrung unterstützt Cocos nicht wirklich das Beenden und Wiederaufnehmen, es verhält sich so, als wäre es erledigt und schaltet sich so ziemlich aus.

Es gibt zwei Dinge, die Sie versuchen können, die erste (und es kam mir gerade in den Sinn) ist CC_DIRECTOR_INIT (kann nicht der genaue Name sein), nachdem der Direktor endete, und bevor Sie es erneut starten möchten.

Die zweite ist, den Quellcode des Directors zu bearbeiten und die Methode end so zu ändern, dass Cocos in einem brauchbaren Zustand bleiben (verhindern Sie, dass die Ansicht freigegeben und der Cache geleert wird usw.). Alternativ dazu können Sie die Methode start so ändern, dass sichergestellt wird, dass Cocos vor dem Start in einem verwendbaren Zustand ist.

Leider macht es Cocos nicht einfach, UIKit + Cocos zu benutzen, aber mit etwas Glück.

2

Was gut funktioniert, ist nur StartAnimation und StopAnimation im Director aufrufen, aber halten Sie die cocos2d Ansicht herum und nur wieder verwenden.

Alle Versuche, cocos2d und seine OpenGL-Ansicht herunterzufahren und später neu zu initialisieren, werden mehr oder weniger Probleme verursachen, weil es wirklich nicht gut genug getestet wurde. Ansonsten funktioniert cocos2d problemlos mit UIKit, es hat jedoch dieselben Probleme wie alle anderen OpenGL ES-Apps, wenn es mit UIKit-Ansichten gemischt wird.

+0

Das Problem bei diesem Ansatz ist, dass das ganze Spiel noch im Speicher ist. Auch habe ich versucht, die aktuelle Szene (die letzte auf dem Stapel) zu knallen, aber es hat die gleichen Probleme. Ich denke, dies ist ein Bereich, in dem sich cocos2d deutlich verbessern muss, da dies kein OpenGL-Problem zu sein scheint, sondern eher ein Problem, dass der Director das GLView nach einmaligem Beenden nicht richtig einrichten konnte. – avf

5

Ich habe mehrere Tage damit verbracht, nach Informationen zu suchen, und werde Ihnen meine eigenen Erfahrungen mitteilen. Ich versuche auch, ein Spiel zu erstellen, das in einen UITableViewController geladen wird, von dem der CCDirector geladen wird, wenn eine Zelle berührt wird. Dies ist ein Game Center rundenbasiertes Spiel, daher das Design (think Words With Friends). Der beste Ansatz, den ich bisher gefunden habe, ist wie folgt (Hinweis: Ich arbeite in 2.0 - wo CCDirector eine UIViewController-Unterklasse ist):

Erstellen Sie in AppDelegate.h ein neues ivar, um die CCGLView zu halten, die erstellt wird aus dem Vorlagencode. Ordnen Sie dann die in didFinishLaunch erstellte CCGLView Ihrem neuen ivar zu. Dadurch kann der Director die ursprünglich erstellte Ansicht wiederverwenden, anstatt sie jedes Mal neu zu erstellen, wenn Sie den CCDirector neu laden, was nach meiner Erfahrung allerlei seltsame Probleme verursacht.

Sie möchten auch eine neue Methode in AppDelegate namens -setupDirector oder etwas ähnliches, wo Sie, nun, richten Sie den Direktor. Dies sollte jedes Mal aufgerufen werden, wenn Sie den CCDirector neu erstellen. Ich habe meine Version unten gepostet. Beachten Sie, dass mein ivar für die CCGLView "GLView" heißt.

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

Darüber hinaus werden Sie einige Änderungen an der Art vornehmen müssen, wie die Vorlage die View-Controller lädt. Normalerweise richtet cocos2D den Navigationscontroller mit director_ als Root-View-Controller ein. Hier möchten Sie Alloc und init Ihr Menü View-Controller und fügen hinzu, dass statt director_:

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

Alles andere in didFinishLaunching kann die gleiche bleiben. Nun, in Ihrem menuViewController in Ihrem startGameButtonPressed Methode, rufen Sie das neu erstellte setupDirector Methode auf Ihrer App-Instanz, die durch den Aufruf verwiesen wird:

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

Ich schließe einen Scheck, um sicherzustellen, das CCDirector nicht noch läuft und wenn es ist, beende es. In Spiel Schicht, wenn die Zeit kommt, dass Sie die View-Controller-Pop wollen, müssen Sie einfach nennen es etwa so:

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

Diese Strömung erlauben sollten Sie frei einen Navigation-Controller verwenden, um Ihre Spielszene schieben mit CCDirector, und blenden Sie diesen View-Controller ein, wenn Sie zu Ihrem UIKit-basierten Hauptmenü zurückkehren möchten. Ich hoffe, das hilft, da ich viel frustrierende Zeit damit verbracht habe, das für mein eigenes Spiel richtig zu machen.