您的位置:首页 > 移动开发 > Cocos引擎

cocos2d-x源码分析::主流程(mainloop)分析

2013-06-30 21:20 344 查看
cocos2d-x的源码分析由这章开始,希望大家在看这篇博文之前,对cocos2d-x有一定的了解,或者做过一些小demo,这样才能更好地了解到这篇文章所说的一些问题

分析现在开始

cocos2d-x程序的入口根据平台的不同而有所区别,但是游戏的入口均是

//main.cpp
...
...
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR    lpCmdLine,
int       nCmdShow)
{
...
AppDelegate app;
...
return CCApplication::sharedApplication()->run(); //游戏入口
}


显然,run就是游戏的开始

不过在run之前程序定义了AppDelegate的一个对象app,这个类的对象在整个程序仅有一个,其实app就是游戏本身。

翻看AppDelegate.h可以发现,AppDelegate是CCApplication的子类,里面的函数也不算太多

我们这里详细说说applicationDidFinishLaunching()

//AppDelegate.cpp
...
...
bool AppDelegate::applicationDidFinishLaunching() {
...
pDirector->setDisplayStats(true);

pDirector->setAnimationInterval(1.0 / 60);//设置帧率

CCScene *pScene = HelloWorld::scene();

pDirector->runWithScene(pScene);//开始运行

return true;
}


这里省略了不少篇幅,我就挑一些重要的说。

setAnimationInterval是设置每帧的时间间隔,(1.0 / 60)可以理解为每秒60帧。

runWithScene就是游戏渲染的开始,把一个CCScene当参数传入,作为游戏的初始画面

AppDelegate定义了这几个函数,那么究竟实在哪里调用的呢?问题很简单,刚才不就看到了一个叫run的函数么?

如果我们翻看一下CCApplication的文件,里面就有run函数

//CCApplication.cpp
...
...
int CCApplication::run()
{
...
if (!applicationDidFinishLaunching())
{
return 0;
}

...

while (1)
{
if (! PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
QueryPerformanceCounter(&nNow);

if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart)
{
nLast.QuadPart = nNow.QuadPart;
CCDirector::sharedDirector()->mainLoop();
}
else
{
Sleep(0);
}
continue;
}
//下面的可以无视
if (WM_QUIT == msg.message)
{
break;
}

if (! m_hAccelTable || ! TranslateAccelerator(msg.hwnd, m_hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

return (int) msg.wParam;
}


这里原来的代码很长,我删掉一些不讲解的代码。

毫无意外,run中调用了applicationDidFinishLaunching。

我们还可以看到run()函数中有一个while(1){}循环,不断进行着游戏的逻辑判断

尤其留意20-28行,if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart)这句意义就是时间间隔大于一定时间(一般来说是大于1/60秒),就运行游戏的主流程(mainloop),否则休眠(sleep),换种说法,每1/60秒运行一次mainloop

mainloop的执行对象是CCDirector,所以说到现在CCApplication的职责到此位置,剩下的任务交由CCDirector来执行。

一查CCDirector中的mainloop竟然是纯虚函数,不过它倒是有一个子类CCDisplayLinkDirector实现了mainloop

//CCDirector.cpp
...
...
void CCDisplayLinkDirector::mainLoop(void)
{
if (m_bPurgeDirecotorInNextLoop)
{
m_bPurgeDirecotorInNextLoop = false;
purgeDirector();
}
else if (! m_bInvalid)
{
drawScene();

CCPoolManager::sharedPoolManager()->pop();
}
}

mainloop的逻辑简单易懂,那么就绘制图像(drawScene)和内存管理(pop)

关于内存管理,可以看我的另一篇博文的介绍

主流程(mainloop)的分析就讲到了这里,欢迎大家来互相讨论,互相交流。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Cocos2d-x 源代码