话说N年前,美女计算机老师讲排序的时候,快速排序方便简单实用,但是是不稳定的排序,所谓不稳定就是,通俗的来讲,排序数组里面有相等的值,排序后要与之前的次序保持不变.即numA = numB;排序前numA在numB前面,那么排序后numA也在numB前面,而不稳定的排序算法,numA可能会再numB的后面. 也许我没有讲清楚,简单理解就是"快速排序有个坑".
不久前,第一次用cocos2d-x3.0开发项目,也就遇到了渲染层级问题。一些layer的层级从底层跑到上层了,比如背景图跑到最上面来了挡住了上面的UI,坑爹啊.
小闫同学很快就找到了原因在node的zorder相同这一点上.因为在cocos2d-x 2.x的时候,这样写
layerA->addchild(sprite1);
layerA->addchild(sprite2);
这样他们默认的层级虽然都是0,但是sprite2是在sprite1上面的.
但是在3.0中这样写,他们的层级是处在未知变化中的,没错,未知变化.
这是因为在cocos2d-x,在visit一个node,会对它的所有child进行一次排序,基准是zorder的大小.
在cocos2d-x2.x中是这样实现这个排序的:
void CCNode::sortAllChildren()
{
if (m_bReorderChildDirty)
{
int i,j,length = m_pChildren->data->num;
CCNode ** x = (CCNode**)m_pChildren->data->arr;
CCNode *tempItem;
// insertion sort
for(i=1; i=0 && ( tempItem->m_nZOrder < x[j]->m_nZOrder || ( tempItem->m_nZOrder== x[j]->m_nZOrder && tempItem->m_uOrderOfArrival < x[j]->m_uOrderOfArrival ) ) )
{
x[j+1] = x[j];
j = j-1;
}
x[j+1] = tempItem;
}
//don't need to check children recursively, that's done in visit of each child
m_bReorderChildDirty = false;
}
}
//很简洁的代码,对child进行了一个基于zoder的插入排序.(插入排序是稳定的排序算法)然而,在cocos2d-x 3.x中
void Node::sortAllChildren()
{
if( _reorderChildDirty ) {
std::sort( std::begin(_children), std::end(_children), nodeComparisonLess );
_reorderChildDirty = false;
}
}
bool nodeComparisonLess(Node* n1, Node* n2)
{
return( n1->getLocalZOrder() < n2->getLocalZOrder() ||
( n1->getLocalZOrder() == n2->getLocalZOrder() && n1->getOrderOfArrival() < n2->getOrderOfArrival() )
);
}
没错,代码除了写的精简点,没什么区别.唯一的区别是用了std::sort代替之前手写的插入排序,std::sort就是快速排序的封装.所以排完序之后就混乱了.其实可以嫌弃插入排序,但是这样让UI层级怎么愉快的玩耍. 不知道cocos2d-x团队有没有好的解决方案,难道是为了我们写更规范的代码?zorder规范管理:addchild(sprite1,1),addChild(sprite2,2)....
好吧,我也没想到好的解决方案,吐槽一下,no zuo no die ,why cocos2d-x3.x try?