auto pNode = Node::create();
this->addChild(pNode);
pNode->setPosition(Vec2::ZERO);
pNode->setScale(1.0f);
pNode->setRotation(0.0f);
pNode->setColor(Color3B::RED);
pNode->setName("node");
pNode->setTag(1);
pNode->setVisible(true);
pNode->setUserData((void*)1);
简简单单的一句代码,可以看出,Node是2dx最基本的类,它是Scene,Layer,Sprite,Label等等的父类,它定义了position,scale,color等常用参数及其的setget方法,还有非常重要的visit、draw方法,它提供子类的渲染接口,具体可以看看!
void Node::visit(Renderer* renderer, const Mat4 &parentTransform, uint32_t parentFlags)
{
// quick return if not visible. children won't be drawn.
if (!_visible)
{
return;
}
uint32_t flags = processParentFlags(parentTransform, parentFlags);
// IMPORTANT:
// To ease the migration to v3.0, we still support the Mat4 stack,
// but it is deprecated and your code should not rely on it
Director* director = Director::getInstance();
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
bool visibleByCamera = isVisitableByVisitingCamera();
int i = 0;
if(!_children.empty())
{
sortAllChildren();
// draw children zOrder < 0
for( ; i < _children.size(); i++ )
{
auto node = _children.at(i);
if ( node && node->_localZOrder < 0 )
node->visit(renderer, _modelViewTransform, flags);
else
break;
}
// self draw
if (visibleByCamera)
this->draw(renderer, _modelViewTransform, flags);
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
(*it)->visit(renderer, _modelViewTransform, flags);
}
else if (visibleByCamera)
{
this->draw(renderer, _modelViewTransform, flags);
}
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
// FIX ME: Why need to set _orderOfArrival to 0??
// Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920
// reset for next frame
// _orderOfArrival = 0;
}
其中sortAllChildren();对不同层级的子类进行排序,从而将zorder最高的和相同层级的最后被addChild的显示出来。
this->draw(renderer, _modelViewTransform, flags);这个函数则画出自身,由于c++的多态性,它将调用自己的draw方法,如,Sprite就会调用
void Sprite::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
// Don't do calculate the culling if the transform was not updated
_insideBounds = (flags & FLAGS_TRANSFORM_DIRTY) ? renderer->checkVisibility(transform, _contentSize) : _insideBounds;
if(_insideBounds)
{
_quadCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, transform);
renderer->addCommand(&_quadCommand);
#if CC_SPRITE_DEBUG_DRAW
_debugDrawNode->clear();
Vec2 vertices[4] = {
Vec2( _quad.bl.vertices.x, _quad.bl.vertices.y ),
Vec2( _quad.br.vertices.x, _quad.br.vertices.y ),
Vec2( _quad.tr.vertices.x, _quad.tr.vertices.y ),
Vec2( _quad.tl.vertices.x, _quad.tl.vertices.y ),
};
_debugDrawNode->drawPoly(vertices, 4, true, Color4F(1.0, 1.0, 1.0, 1.0));
#endif //CC_SPRITE_DEBUG_DRAW
}
}
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
(*it)->visit(renderer, _modelViewTransform, flags);
这里是一个递归,从而渲染出节点树所有的节点!
2dx中的大循环中就是调用Node的visit方法,我们去看看
main.cpp -> director->mainLoop() -> drawScene() -> _runningScene->render(_renderer) -> visit(renderer, Mat4::IDENTITY, 0);
AppDelegate app;
return Application::getInstance()->run();
.....
while(!glview->windowShouldClose())
{
QueryPerformanceCounter(&nNow);
if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart)
{
nLast.QuadPart = nNow.QuadPart;
director->mainLoop();
glview->pollEvents();
}
else
{
Sleep(0);
}
}
......
else if (! _invalid)
{
drawScene();
// release the objects
PoolManager::getInstance()->getCurrentPool()->clear();
}
......
if (_runningScene)
{
//clear draw stats
_renderer->clearDrawStats();
//render the scene
_runningScene->render(_renderer);
_eventDispatcher->dispatchEvent(_eventAfterVisit);
}
......
//visit the scene
visit(renderer, Mat4::IDENTITY, 0);
这个visit就是Node的visit函数。