Cocos2d-x 游戏引擎框架运行逻辑图 [ win32平台 ]
main 方法是win32工程项目的入口方法, 所以我们从这里开始分析
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
...
return CCApplication::sharedApplication()->run();
}
查找源代码后发现它最终调用的是
CCApplication:
run方法.
int CCApplication::run()
{
...
while (1)
{
if (! PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
...
CCDirector::sharedDirector()->mainLoop();
}
}
return ( int) msg.wParam;
}
这里的关键方法调用就是CCDirector 对应的mainLoop方法。需要注意的这里分析的win32平台下方法调用,不同平台下的运行逻辑是不尽相同的。但是最终都会调用mainLoop来管理引擎逻辑。
mainLoop方法是定义在CCDirector中的抽象方法,它的实现是位于同一文件中的CCDisplayLinkDirector类。
void CCDisplayLinkDirector::mainLoop(void)
{
if (m_bPurgeDirecotorInNextLoop) // 1
{
m_bPurgeDirecotorInNextLoop = false;
purgeDirector();
}
else if (! m_bInvalid)
{
drawScene(); // 2
// release the objects
CCPoolManager::sharedPoolManager()->pop(); // 3
}
}
{
if (m_bPurgeDirecotorInNextLoop) // 1
{
m_bPurgeDirecotorInNextLoop = false;
purgeDirector();
}
else if (! m_bInvalid)
{
drawScene(); // 2
// release the objects
CCPoolManager::sharedPoolManager()->pop(); // 3
}
}
1. 代码首先判断是否需要释放CCDirector, 如果需要,则删除CCDirector占用的资源。通常,游戏结束才执行这个步骤。
2. 调用drawScene方法,绘制当前场景并进行必要的处理。
3. 弹出自动回收池,使得这一帧被放入回收池的对象全部释放。
接下里就是drawScene,看下代码
void CCDirector::drawScene(void )
{
// calculate "global" dt
calculateDeltaTime();
//tick before glClear: issue #533
if (! m_bPaused)
{
m_pScheduler->update(m_fDeltaTime); // 1
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* to avoid flickr, nextScene MUST be here: after tick and before draw.
XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */
if (m_pNextScene)
{
setNextScene();
}
kmGLPushMatrix(); // 压栈当前矩阵,方便在绘制结束后还原原始矩阵
// draw the scene
if (m_pRunningScene)
{
m_pRunningScene->visit(); // 2
}
// draw the notifications node
if (m_pNotificationNode)
{
m_pNotificationNode->visit();
}
if (m_bDisplayStats)
{
showStats(); // use CCLabelTTF to draw profile data
}
kmGLPopMatrix();
m_uTotalFrames++;
// swap buffers
if (m_pobOpenGLView)
{
m_pobOpenGLView->swapBuffers();
}
if (m_bDisplayStats)
{
calculateMPF();
}
}
1. 使用CCScheduler对象
m_pScheduler来调度事件
2. 使用Scene来做流程控制, 并显示当前游戏场景
至此, 游戏框架的运行逻辑已经很清楚了。熟悉游戏的运行框架有助于我们从整体上把握和学习一个引擎。