2012-06-14 50 views
7

我有一個使用UIKit菜單的cocos2d動力遊戲,所以我只使用一個viewcontroller的框架,這是遊戲本身。另外,它只有一個場景。由於cocos2d的2.0導演本身就是一個UIViewController子類,所以當用戶點擊開始按鈕,我只是把它在我的MenuViewControllercocos2d 2.0-rc2:結束導演並重新啓動

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

這工作得很好,第一次調用該方法,用戶開始時第一場比賽。遊戲結束後,我打電話給[[CCDirector sharedDirector] end]

大部分導演設置都是在appDelegate中完成的(它取自默認的Cocos2d模板)。我只將CCGLView作爲保留屬性放入我的MenuViewController,因爲否則在調用[[CCDirector sharedDirector] end]時應用程序崩潰,並且CCGLView未保留。我認爲這可能是一個cocos2d錯誤。在[[CCDirector sharedDirector] end]框架調用[self setView:nil],但它仍然試圖訪問視圖(可能在另一個線程)。

現在的問題是,在我上面的方法的第二個電話(當用戶想從菜單啓動另一個遊戲時),startGameButtonPressed,導演被推動,但屏幕仍然是黑屏。遊戲正在運行和響應,我什麼也沒看到。有人能幫我解決嗎?

+0

我真的可以使用這個問題的答案。這是我現在申請的關鍵。 – Echilon

回答

8

好的,我有同樣的問題,我能夠「修復它」。

設置CCGLView和[director setView:]時,即使彈出控制器,場景仍然存在。發生的唯一情況是現場被停止。

所以爲了讓「重啓」工作,你必須檢查是否已經有一個正在運行的場景(即使它已經停止,而不是runWithScene:你使用replaceScene:

這裏是我的代碼,所以你可以看到:

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

} 

希望這個代碼將會幫助你,因爲我花了一整天試圖弄清楚這一點。 它可能不是正確的方式,甚至最漂亮的方式,但它的工作:)

編輯: 另外,請不就是如果你彈出的Cocos2D場景,你不必[[CCDirector sharedDirector] end]作爲動畫將在視圖被解除分配/刪除時停止。

+0

我認爲這樣做的原因是,您不要將導演作爲視圖控制器,而是將GLView附加到您自己的視圖上。這可能是比我更好的方法。 – avf

+0

非常感謝這篇文章@gmogames。我花了幾個小時與此搏鬥。 – Echilon

+0

那麼說..謝謝您的寶貴答案... –

0

根據我的經驗,科科斯並不真的支持結束和恢復,它的行爲就像完成了一樣,並且幾乎將自己關閉。

有兩件事你可以嘗試,第一件事(我想到的是)在導演結束之後,又想再次開始之前,致電CC_DIRECTOR_INIT(可能不是確切的名字)。

第二個是編輯導演源代碼,並修改end方法,以便它使cocos保持在可用狀態(阻止它釋放視圖並清除緩存等)。或者,您可以修改start方法,以確保Cocos在啓動之前處於可用狀態。

不幸的是,科科斯並沒有讓我們很容易地使用UIKit + Cocos,但運氣很好。

2

最好的方法是在導演中調用startAnimation和stopAnimation,但保留cocos2d視圖並重新使用它。

任何試圖關閉cocos2d及其OpenGL視圖並在稍後重新初始化的嘗試都會導致更多或更少的問題,因爲它實際上未經過足夠好的測試。除此之外,cocos2d在UIKit中工作得很好,它與其他OpenGL ES應用程序在與UIKit視圖混合時具有相同的問題。

+0

該方法的問題在於整個遊戲仍在記憶中。另外,我嘗試彈出當前場景(堆疊中的最後一個場景),但它具有相同的問題。我認爲這是一個cocos2d需要顯着提高的領域,因爲這似乎不是一個OpenGL問題,但更多的問題是導演無法在結束一次後正確設置GLView。 – avf

5

我花了好幾天的時間尋找與此相關的信息,並將與您分享我自己的經驗。我也試圖創建一個加載到UITableViewController中的遊戲,當單元被觸摸時,CCDirector將從該遊戲加載。這是一個遊戲中心回合制遊戲,因此設計(思考與朋友說話)。我發現迄今爲止最好的方法如下(注意我在2.0中工作 - 其中CCDirector是UIViewController的子類):

在AppDelegate.h中,創建一個新的ivar以容納創建的CCGLView來自模板代碼。然後將在didFinishLaunching中創建的CCGLView分配給您的新伊娃。這允許導演重新使用最初創建的視圖,而不是在每次重新加載CCDirector時嘗試重新創建它,這似乎會導致我體驗中的各種奇怪問題。

您還想在AppDelegate中創建一個名爲-setupDirector的新方法或類似的東西,您可以在其中設置導演。這應該在每次重新創建CCDirector時調用。我已在下面發佈我的版本。請注意,CCGLView的我的ivar被稱爲「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]; 
} 

此外,您還需要對模板加載視圖控制器的方式進行一些更改。通常情況下,cocos2D會以director_作爲根視圖控制器來設置導航控制器。在這裏,你想要的Alloc和初始化你的菜單視圖控制器,並添加director_的,與其:

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

其他的一切在didFinishLaunching可以保持不變。現在,在你的startGameButtonPressed方法你menuViewController,您將調用新創建的setupDirector方法您的應用實例,它是通過調用引用:

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

我包括檢查,以確保CCDirector沒有仍在運行如果是,就結束它。在你的遊戲層,到時候要彈出視圖控制器,你可以簡單的調用它像這樣:

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

這種流動應該讓你自由地使用導航控制器,把你的遊戲場景CCDirector,當你想回到基於UIKit的主菜單時彈出視圖控制器。我希望這會有所幫助,因爲我花了很多時間試圖爲自己的比賽做好準備。

相關問題