bug cocos2d-x 3.1 Node::sortAllChildren

先介绍一下,3.1版本 中 Node::sortAllChildren 的作用:

Node在绘制前,需要先将它的子节点(children)进行排序,然后按顺序地绘制出来,实现对应的层次关系。

一般而言,想要让一个node在父节点中显示得比较靠前,那就要把其zorder设置得较大一点,zorder大的会比zorder小的绘制得前,在3.1版本中,zorder改成了_localZOrder

然后有一种做法,假设有一个layer,上面有n个sprite,他们的zorder都一样,此时较后添加到layer的sprite,在绘制时会靠前,因为其排在了children队列后面。所以在都以相同的zorder添加到layer后,想要某个sprite显示在最前方,只要重新以相同的zorder来reorderChild就行了(相当于最后被添加到队列中)。

而sortAllChildren起的就是排序的作用,

在旧版本中,排序是遍历形势来比较换位的。

而3.1版本使用std::sort来进行排序,然而问题来了,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。这回影响什么呢?那么就要再说一个事,前面说过,主要绘制顺序会根据_localZOrder值来排序的。

但!!!当 _localZOrder 相同时,会判断另一个值,那就是 _orderOfArrival ,当调用reorderChild时,设置child的zorder同时也会设置orderOfArrival,这是个自增长的数,用来记录添加的子节点的顺序,就是说每加到父节点的子节点,其 _orderOfArrival 会被赋值,然后在sortAllChildren时,如果判断到 _localZOrder 相同,那么就会进行 _orderOfArrival 的判断,然后在一帧绘制完成后,因为children已经排序完毕,所以所有node的 _orderOfArrival 会被重新赋值为 0 。按照以前的版本,这样做是没问题的,但3.1版本使用快速排序,“多个相同的值的相对位置也许会在算法结束时产生变动”,所以当到了下一帧,所有节点的_orderOfArrival都会相同,而_localZOrder本来就是相同的,所以其排序后的位置顺序就会不稳定了,有时这个靠前,有时这个靠后,这就是所谓的bug了,我还发现,ios和android排序后的结果也不一样。

所以,大家要注意了,尽量不要把zorder设置成同一个值或者不设置,应该自己定好不同的zorder,这样才不会出现混乱。

你可能感兴趣的:(cocos2d-x)