一、引擎绘制节点的流程
在cocos2d-x中是通过分配一段连续的内存来存储children,当新的child被add进来,他会默认被添加到后面,如果不够会重新分配当前当前最大的两倍的容量,和STL的策略是一样的。在每一帧进行渲染的时候,根据child的zorder的大小进行排序(其实就是冒泡排序),zorder最小的排在前面进行绘制。
引擎都是以OpenGL为基础进行图像的绘制的,在main.cpp中完成OpenGL的准备以及绘制的流程的开始。
(以win下的流程为例)
CCEGLView* eglView = CCEGLView::sharedOpenGLView(); //触发OpenGL的初始化
CCEGLView* CCEGLView::sharedOpenGLView()
{
static CCEGLView* s_pEglView = NULL;
if (s_pEglView == NULL)
{
s_pEglView = new CCEGLView(); //
if (!s_EglView->Create())
{
delete s_pEglView;
s_pEglView = NULL;
}
}
return s_pEglView;
}
CCEGLView::Create()函数主要做Windowos窗体程序的相关设置,调用CCEGLView::initGL()
bRet = initGL()
在initGL中准备各种OpenGL的设置。
int ret = CCApplication::sharedApplication()->run();
run函数调用applicationDidFinishLaunching()和开始一个死循环,驱动每一帧的绘制。
AppDelegate::applicationDidFinishLaunching()中初始化CCDirector(实际创建的是CCDisplayLinkDirector),设置设计尺寸(setDesignResolutionSize),设置资源路径(setResourceDirectory),创建一个场景,以这个场景作为第一个场景来运行。
CCScene直接继承自CCNode,项目节点树的根节点一定是CCScene,既绘制流程一定是从一个场景开始绘制。死循环就是应用的主循环,每次循环判断是否需要绘制一帧,如果是就开始绘制,否则。。。
while(1)
{
//
if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart) //判断是否需要绘制,当前时刻与上次绘制时刻的差大于帧速
{
nLast.QuadPart = nNow.QuadPart; //更新上次绘制时刻
CCDirector::sharedDirector()->mainLoop(); //进入绘制流程
} else {
Sleep(0); //休息一段时间
}
}
CCDisplayLinkDirector::mainLoop()调用drawScene(),CCDirector::drawScene()负责切换场景,以及从一个场景开始逐个节点访问并绘制。
if (m_pNextScene)
{
setNextScene();
}
if (m_pRuningScene)
{
m_pRunningScene->visit();
}
CCNode::visit()计算本节点的变形并更新模型视图矩阵,遍历访问子节点和绘制自身。
if (m_pChildren && m_pChildren->count() > 0)
{
sortAllChildren(); //
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();
for(; i < arrayData->num; i++)
{
pNode = (CCNode*)arrayData->arr[i];
if (pNode)
{
pNode->visit();
}
}
} else {
this->draw();
}
这样中序遍历节点树后,一帧的绘制就完成了。