做个游戏的应该都知道,我们的游戏一般是在一个死循环中渲染的,比如下面:
float dt;
while (1)
{
...
update(dt); //通过时间差更新数据
present(dt);//通过时间差呈现、绘制游戏画面
...
}
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// create the application instance
AppDelegate app; //实例化应用代理对象,这个对象是CCApplication的子类,
//实现了applicationDidFinishLaunching()等方法,目的
//目的是为了在底层框架中回调,做一些初始化或者结尾的工作
CCEGLView* eglView = CCEGLView::sharedOpenGLView();//继承和封装了一些对Opengl接口的操作。不同平台实现不一样
eglView->setViewName("TestCpp");
eglView->setFrameSize(480, 320);
return CCApplication::sharedApplication()->run();//一个单实例类,通过run方法进入引擎主循环
}
int CCApplication::run()
{
......
// Initialize instance and cocos2d.
if (!applicationDidFinishLaunching())//AppDelegate的回调方法,主要就是初始化CCDirector等数据,方便显示第一个场景
{
return 0;
}
......
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)//判断时间差是不是达到了到下一帧的条件
{ <span style="white-space:pre"> </span>//主要是看锁定多少的FPS
nLast.QuadPart = nNow.QuadPart;
CCDirector::sharedDirector()->mainLoop();//进入引擎的主循环
}
else
{
Sleep(0);
}
continue;
}
......
}
return (int) msg.wParam;
}
void CCDisplayLinkDirector::mainLoop(void)
{
if (m_bPurgeDirecotorInNextLoop)//进入下一个主循环,也就是结束这次的主循环,就净化,也就是一些后期处理
{
m_bPurgeDirecotorInNextLoop = false;
purgeDirector();
}
else if (! m_bInvalid)
{
drawScene();//绘制屏幕
// release the objects
CCPoolManager::sharedPoolManager()->pop();//释放一些没有用的对象,主要保件内存的合理管理
}
}
void CCDirector::drawScene(void)
{
// calculate "global" dt
calculateDeltaTime();//计算时间差
//tick before glClear: issue #533
if (! m_bPaused) //如果不暂停,就更新数据
{
m_pScheduler->update(m_fDeltaTime);//调度者对象,是整个框架中,非常重要的东东,他负责者引擎中精灵、动作等的调度
//而里面所用的数据结构的组织,一定程度决定者引擎的效率。
}
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();//如果有m_pNextScene对象不为空,就说明需要调用到新的场景中,
//在其中onEnter()、onEnterTransitionDidFinish()等函数被回调。
}
kmGLPushMatrix();//opengl:把当前矩阵放到栈中
// draw the scene
if (m_pRunningScene)
{
m_pRunningScene->visit();//通过访问方法,去绘制场景中包含的每个层和每个层中的每个节点的draw,
//这里面是一个递归的过程,其中transform()方法实现,opengl矩阵的变化<span style="white-space:pre"> </span>//,移动,旋转等。
}
// draw the notifications node
if (m_pNotificationNode)
{
m_pNotificationNode->visit();//绘制通知节点,目前我也不知道这个是什么!
}
if (m_bDisplayStats)
{
showStats();
}
kmGLPopMatrix();//opengl:把当前矩阵从栈中移除,回复之前的矩阵
m_uTotalFrames++;//记录总帧数
// swap buffers
if (m_pobOpenGLView)
{
m_pobOpenGLView->swapBuffers();//opengl:交换帧缓冲区,把绘制的东东显示在屏幕。
}
if (m_bDisplayStats)
{
calculateMPF();
}
}