学习cocos2dx渲染流程
本文将深入学习Cocos2d-x 2.x版本的渲染流程。我们从程序的起点——main函数开始分析。
在main函数中,通常会有如下代码:
return CCApplication::sharedApplication()->run();
调用CCApplication::sharedApplication()->run()后,程序会进入该函数。CCApplication类是一个跨平台的类,不同平台有不同的实现方式。例如,在iOS平台上,其实现文件是.mm文件。不同平台实现死循环的方式也不同,但本质都是为了实现循环逻辑。以下是该函数中的一个关键代码片段,展示了一个死循环:
// 一个死循环
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();
}
}
}
在这个死循环中,会根据条件不断调用CCDirector类中的mainLoop函数。进入mainLoop函数后,会调用drawScene函数:
drawScene();
drawScene函数的代码片段如下:
// 绘制场景
if (m_pRunningScene)
{
m_pRunningScene->visit();
}
// 绘制通知节点
if (m_pNotificationNode)
{
m_pNotificationNode->visit();
}
可以看到,drawScene函数中调用了visit方法。在Cocos2d-x中,所有的节点(Node)都继承自CCNode类。下面我们详细分析CCNode类中的visit函数:
void CCNode::visit()
{
// 如果不可见,则快速返回,子节点也不会被绘制
if (!m_bVisible)
{
return;
}
kmGLPushMatrix();
if (m_pGrid && m_pGrid->isActive())
{
m_pGrid->beforeDraw();
}
this->transform();
CCNode* pNode = NULL;
unsigned int i = 0;
if (m_pChildren && m_pChildren->count() > 0)
{
sortAllChildren();
// 绘制zOrder < 0的子节点
ccArray *arrayData = m_pChildren->data;
for (; i < arrayData->num; i++)
{
pNode = (CCNode*)arrayData->arr[i];
if (pNode && pNode->m_nZOrder < 0)
{
pNode->visit();
}
else
{
break;
}
}
// 自身绘制
this->draw();
// 获取所有子节点,调用子节点的visit方法
for (; i < arrayData->num; i++)
{
pNode = (CCNode*)arrayData->arr[i];
if (pNode)
{
pNode->visit();
}
}
}
else
{
// 调用自身的绘制方法,实现图像绘制
this->draw();
}
// 为下一帧重置顺序
m_uOrderOfArrival = 0;
if (m_pGrid && m_pGrid->isActive())
{
m_pGrid->afterDraw(this);
}
kmGLPopMatrix();
}
visit函数的主要逻辑如下:
- 首先检查节点是否可见,如果不可见则直接返回。
- 保存当前的矩阵状态(
kmGLPushMatrix)。 - 如果网格(
Grid)处于激活状态,则调用beforeDraw方法。 - 进行节点的变换操作(
transform)。 - 如果节点有子节点,则对所有子节点进行排序。
- 先绘制
zOrder小于0的子节点。 - 绘制自身节点(
draw方法)。 - 绘制剩余的子节点。
- 重置顺序(
m_uOrderOfArrival = 0)。 - 如果网格处于激活状态,调用
afterDraw方法。 - 恢复矩阵状态(
kmGLPopMatrix)。
通过以上步骤,Cocos2d-x完成了整个场景的渲染流程。