天天看點

【玩轉cocos2d-x之三】cocos2d-x遊戲是怎麼跑起來的

原創作品,轉載請标明:http://blog.csdn.net/jackystudio/article/details/12554167

雖然cocos2d-x v3.0 alpha版已經出來了,也改進了不少,有興趣的可以去嘗嘗鮮。因為後面可能還會配合cocoStudio寫一下部落格,而現在v1.0.0.0版本需要配合cocos2d-x v2.2.0使用。是以這裡選擇了V2.2.0版的cocos2d-x。

一個新的東西,從頭開始吧!從HelloWorld出發看一下一個cocos2d-x遊戲是怎麼跑起來的。先看看它的結構。

【玩轉cocos2d-x之三】cocos2d-x遊戲是怎麼跑起來的

1.main函數

還是原來配方還是熟悉的味道。。。霸氣的main函數依然是程式的入口點:

[cpp]  view plain copy

  1. //main.cpp  
  2. int APIENTRY _tWinMain(HINSTANCE hInstance,  
  3.                        HINSTANCE hPrevInstance,  
  4.                        LPTSTR    lpCmdLine,  
  5.                        int       nCmdShow)  
  6. {  
  7.     UNREFERENCED_PARAMETER(hPrevInstance);//該宏用于通知編譯器不用檢測變量是否使用,如果你喜歡用LV4級的警告。  
  8.     UNREFERENCED_PARAMETER(lpCmdLine);  
  9.     // create the application instance  
  10.     AppDelegate app;//建立AppDelegate執行個體  
  11.     CCEGLView* eglView = CCEGLView::sharedOpenGLView();//擷取CCEGLView的單一執行個體,因為還未建立,是以這裡會進行建立  
  12.     eglView->setViewName("HelloCpp");//設定eglView屬性  
  13.     eglView->setFrameSize(2048, 1536);  
  14.     eglView->setFrameZoomFactor(0.4f);  
  15.     return CCApplication::sharedApplication()->run();//調用run運作程式  
  16. }  

其中:

(1)AppDelegate繼承于CCApplication,是整個遊戲的程式類,如果有用過MFC的就很清楚,類似于CxxxApp。

(2)CCEGLView封裝了使用openGL作為顯示底層API的一個基本的Windows窗體的建立和控制。

可以簡單的認為,一個控制了程式的邏輯,而另一個負責遊戲的顯示。

2.CCEGLView類

我們先看看上一步的CCEGLView::sharedOpenGLView()做了什麼。

[cpp]  view plain copy

  1. CCEGLView* CCEGLView::sharedOpenGLView()  
  2. {  
  3.     if (s_pEglView == NULL)//s_pEglView是一個CCEGLView指針,靜态成員變量  
  4.     {  
  5.         s_pEglView = new CCEGLView();  
  6.         if(!s_pEglView->Create())//main中調用時,會執行這一步  
  7.         {  
  8.             delete s_pEglView;  
  9.             s_pEglView = NULL;  
  10.         }  
  11.     }  
  12.     return s_pEglView;  
  13. }  

再看看,create做了什麼

[cpp]  view plain copy

  1. //...  
  2. m_hWnd = CreateWindowEx(               // 建立窗體  
  3. WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,    // Extended Style For The Window  
  4. kWindowClassName,                                    // Class Name  
  5. wszBuf,                                                // Window Title  
  6. WS_CAPTION | WS_POPUPWINDOW | WS_MINIMIZEBOX,        // Defined Window Style  
  7. 0, 0,                                                // Window Position  
  8. 1000,                                               // Window Width  
  9. 1000,                                               // Window Height  
  10. NULL,                                                // No Parent Window  
  11. NULL,                                                // No Menu  
  12. hInstance,                                            // Instance  
  13. NULL );  

看到上面這一步了吧,使用Win32寫過窗體的童鞋,就知道建立一個窗體需要哪些動作:

(1)填充視窗類結構WNDCLASS

(2)注冊視窗

(3)建立視窗

(4)顯示視窗(這一步沒有在CCEGLView中實作,而是在後面的CCApplication中實作,因為這裡視窗的屬性還沒有進行設定)

一樣的,建立一個cocos2d-x的win32視窗也是要經過這些步驟。具體的就看源碼吧,這裡不逐句解釋了。就是要注意有個WinProc函數,是用于處理主視窗消息。

3.CCApplication類

我們再看看CCApplication::sharedApplication()->run()執行的又是什麼東西。

[cpp]  view plain copy

  1. int CCApplication::run()  
  2. {  
  3.     PVRFrameEnableControlWindow(false);  
  4.     // Main message loop:  
  5.     MSG msg;  
  6.     LARGE_INTEGER nFreq;  
  7.     LARGE_INTEGER nLast;  
  8.     LARGE_INTEGER nNow;  
  9.     QueryPerformanceFrequency(&nFreq);//擷取目前系統頻率和計數  
  10.     QueryPerformanceCounter(&nLast);  
  11.     // Initialize instance and cocos2d.  
  12.     if (!applicationDidFinishLaunching())//虛函數,調用子類的重載,這裡也會設定一些顯示視窗的屬性  
  13.     {  
  14.         return 0;  
  15.     }  
  16.     CCEGLView* pMainWnd = CCEGLView::sharedOpenGLView();擷取CCEGLView的單一執行個體  
  17.     pMainWnd->centerWindow();  
  18.     ShowWindow(pMainWnd->getHWnd(), SW_SHOW);//這裡顯示視窗  
  19.     while (1)//消息循環  
  20.     {  
  21.         if (! PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))  
  22.         {  
  23.             // 擷取目前的計數  
  24.             QueryPerformanceCounter(&nNow);  
  25.             // 判斷時間流逝,是否該繪制下一幀  
  26.             if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart)  
  27.             {  
  28.                 nLast.QuadPart = nNow.QuadPart;  
  29.                 CCDirector::sharedDirector()->mainLoop();//渲染場景(清除顯示裝置,重繪場景)  
  30.             }  
  31.             else  
  32.             {  
  33.                 Sleep(0);  
  34.             }  
  35.             continue;  
  36.         }  
  37.         if (WM_QUIT == msg.message)//擷取退出消息,跳出循環  
  38.         {  
  39.             // Quit message loop.  
  40.             break;  
  41.         }  
  42.         // 處理Windows消息  
  43.         if (! m_hAccelTable || ! TranslateAccelerator(msg.hwnd, m_hAccelTable, &msg))  
  44.         {  
  45.             TranslateMessage(&msg);  
  46.             DispatchMessage(&msg);  
  47.         }  
  48.     }  
  49.     return (int) msg.wParam;  
  50. }  

好了,解釋的應該算比較清楚了,雖然沒有每一個函數都進去。。。這裡再總結一下:

(1)首先先擷取目前系統的頻率和計數。這是一個很大的值,是以用了一個LARGE_INTEGER型變量來存儲。

(2)調用子類的applicationDidFinishLaunching(),執行進入程式後的一些初始化工作。

(3)擷取CCEGLView單例,顯示視窗。

(4)進入循環While(1),重繪每一幀的場景。

好了,更多關于CCApplication的請看源碼吧。

4.AppDelegate類

從上面的分析我們知道CCApplication::run()函數中會調用子類(AppDelegate)的applicationDidFinishLaunching函數,而這裡也就是我們要設定視窗屬性和運作遊戲的地方了。

[cpp]  view plain copy

  1. bool AppDelegate::applicationDidFinishLaunching() {  
  2.     //第一次初始化導演,導演也是個單例類  
  3.     CCDirector* pDirector = CCDirector::sharedDirector();  
  4.     //獲得CCEGLView單例,設定視窗屬性和fps等等  
  5.     CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();  
  6.     ...  
  7.     // 建立場景  
  8.     CCScene *pScene = HelloWorld::scene();  
  9.     // 進入場景  
  10.     pDirector->runWithScene(pScene);  
  11.     return true;  
  12. }  

好了,最後再總結成一張圖,cocos2d-x遊戲就是這麼跑起來的~

【玩轉cocos2d-x之三】cocos2d-x遊戲是怎麼跑起來的