刚阅读完了cocos2d-x的大部分源码,感觉受益匪浅,cocos2d-x的代码并不复杂,可读性很强,并且其中一部分精华的部分也可以运用到工作中去,相得益彰。现在看来,阅读源代码的最好方式是top-down的方式,先弄懂整个框架,再重点突破重要和感兴趣的模块。废话少说,先看看coscos2d-x的框架是怎样的,如何运行起来。
先让我们看看测试用例TestCpp中的主函数,也是整个Win32程序的入口。
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // create the application instance AppDelegate app; CCEGLView* eglView = CCEGLView::sharedOpenGLView(); eglView->setViewName("TestCpp"); eglView->setFrameSize(480, 320); return CCApplication::sharedApplication()->run(); }这个入口有2个非常重要的类CCEGLView和CCApplication,在整个程序中都是单例。
m_hDC = GetDC(m_hWnd); SetupPixelFormat(m_hDC); //SetupPalette(); m_hRC = wglCreateContext(m_hDC); wglMakeCurrent(m_hDC, m_hRC);CCEGLView::initGL中设置了像素的格式,创建了OpenGL的RenderContext,OpenGL最终渲染的结果会显示到该窗口的DC上。
CCApplication* CCApplication::sharedApplication() { CC_ASSERT(sm_pSharedApplication); return sm_pSharedApplication; }这个函数中的sm_pSharedApplication是在什么地方初始化的呢?聪明的你很快就会发现其实前面有一个AppDelegate app,AppDelegate是Application的子类,在这个子类的构造函数中声明了这个全局唯一的静态变量。
CCApplication::CCApplication() : m_hInstance(NULL) , m_hAccelTable(NULL) { m_hInstance = GetModuleHandle(NULL); m_nAnimationInterval.QuadPart = 0; CC_ASSERT(! sm_pSharedApplication); sm_pSharedApplication = this; }由此Application的单例也有了。Application::Run()做了什么呢,让整个程序运行起来了呢?
int CCApplication::run() { PVRFrameEnableControlWindow(false); // Main message loop: MSG msg; LARGE_INTEGER nFreq; LARGE_INTEGER nLast; LARGE_INTEGER nNow; QueryPerformanceFrequency(&nFreq); QueryPerformanceCounter(&nLast); // Initialize instance and cocos2d. if (!applicationDidFinishLaunching()) { return 0; } CCEGLView* pMainWnd = CCEGLView::sharedOpenGLView(); pMainWnd->centerWindow(); ShowWindow(pMainWnd->getHWnd(), SW_SHOW); while (1) { if (! PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // Get current time tick. QueryPerformanceCounter(&nNow); // If it's the time to draw next frame, draw it, else sleep a while. if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart) { nLast.QuadPart = nNow.QuadPart; CCDirector::sharedDirector()->mainLoop(); } else { Sleep(0); } continue; } if (WM_QUIT == msg.message) { // Quit message loop. break; } // Deal with windows message. if (! m_hAccelTable || ! TranslateAccelerator(msg.hwnd, m_hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; }先跳过applicationDidFinishLaunching()部分(这部分和测试用例有关系),可以看到在while主循环中做了两件事:
void CCDisplayLinkDirector::mainLoop(void) { if (m_bPurgeDirecotorInNextLoop) { m_bPurgeDirecotorInNextLoop = false; purgeDirector(); } else if (! m_bInvalid) { drawScene(); // release the objects CCPoolManager::sharedPoolManager()->pop(); } }导演类的的每帧做的最重要的事情就是drawScene,
void CCDirector::drawScene(void) { ...... if (! m_bPaused) { m_pScheduler->update(m_fDeltaTime); } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // draw the scene if (m_pRunningScene) { m_pRunningScene->visit(); } // swap buffers if (m_pobOpenGLView) { m_pobOpenGLView->swapBuffers(); } }
读者仔细看看就会发现这个函数做了两个方面的工作,:
1. 更新调度器m_pScheduler,比如场景中的动作等,后面的博文会详细的分析
2. 绘制场景中的对象结点,树形的方式
至此,cocos2d-x的整体框架就非常清晰的摆在我们面前了,后面就开始解剖麻雀了^_^