微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

cocos2dx-ui的渲染机制

渲染系统是游戏引擎里面最重要的一个模块之一了,如何遍历UI树,如何将UI合理的渲染在屏幕上,如何选择渲染的顺序,这是渲染系统最需要考虑的。其实遍历的顺序就决定了渲染的顺序。

Cocos2d-x的渲染函数是通过Node::visit来进行的,首先看看这个函数干了什么吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
void Node::visit(Renderer*renderer, const Mat4&parentTransform,uint32_tparentFlags)
{
//quickreturnifnotvisible.childrenwon'tbedrawn.
if (!_visible)
{
return ;
}
uint32_tflags=processparentFlags(parentTransform,parentFlags);
bool visibleByCamera=isVisitableByVisitingCamera();
int i=0;
(!_children.empty())
{
sortAllChildren();
//drawchildrenzOrder<0
for (;i<_children.size();i++)
{
autonode=_children.at(i);
(node&&node->_localZOrder<0)
node->visit(renderer,_modelViewTransform,flags);
else
break ;
}
//selfdraw
(visibleByCamera)
this ->draw(renderer,flags);
(autoit=_children.cbegin()+i;it!=_children.cend();++it)
(*it)->visit(renderer,flags);
}
else (visibleByCamera)
{
ottom:auto!important; float:none!important; height:auto!important; left:auto!important; line-height:1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,flags);
}
}

然后可以开始一步一步分析代码了,首先快速去掉不可见的元素,并且不绘制它的子元素。_visible的判断就干了这件事情。

然后判断子节点是否为空,子节点为空的判断是否在摄像机可视范围内,只有在可视范围内才进行绘制,如下:

4
(visibleByCamera)
ottom:auto!important; float:none!important; height:auto!important; left:auto!important; line-height:1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,flags);
然后重点就是子节点非空的情况了,子节点非空的时候,先将所有子节点进行排序,根据什么排序呢?走进sortAllChildren函数看一看

8
Node::sortAllChildren()
(_reorderChildDirty)
{
std::sort(std::begin(_children),std::end(_children),nodeComparisonLess);
_reorderChildDirty= false }
还要继续深入nodeComparisonLess函数

6
nodeComparisonLess(Node*n1,Node*n2)
(n1->getLocalZOrder()<n2->getLocalZOrder()||
(n1->getLocalZOrder()==n2->getLocalZOrder()&&n1->getorderOfArrival()<n2->getorderOfArrival())
);
可以看到它是根据LocalZOrder进行排序的,当LocalZOrder相同的情况下,根据加入UI树的顺序排序。那么LocalZOrder就是非常重要的元素了,排序好的子节点是基于LocalZOrder递增的。接下来看看子节点是如何进行绘制的。

10
//drawchildrenzOrder<0
(;i<_children.size();i++)
{
autonode=_children.at(i);
(node&&node->_localZOrder<0)
ottom:auto!important; float:none!important; height:auto!important; left:auto!important; line-height:1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,flags);
else
;
首先绘制_localZOrder小于0的,然后绘制自身 最后绘制大于等于0的

6
//selfdraw
(visibleByCamera)
ottom:auto!important; float:none!important; height:auto!important; left:auto!important; line-height:1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,flags);
(autoit=_children.cbegin()+i;it!=_children.cend();++it)
ottom:auto!important; float:none!important; height:auto!important; left:auto!important; line-height:1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,flags);

下面是一张图便于理解

所以UI树的遍历方法就是中序遍历的深度优先算法。总结如下:

1.遍历左边子节点

2.遍历根节点

3.遍历右边子节点

通过这样的方法,可以保证UI的绘制顺序可以通过_localZOrder 来调节,小于0的将被首先绘制,然后再绘制父节点。然后再绘制大于0的。

所以综上所述,_localZOrder 越小的元素将会被优先绘制

原文地址:https://www.jb51.cc/cocos2dx/341556.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐