cocos2d-x通過zOrder來控制每個節點顯示出來的順序原理
阿新 • • 發佈:2018-12-15
我們為了控制一個節點的顯示層級關係,通常會用到設定zOrder來控制,那麼,其中的原理又是怎樣的呢?下面來探究一下。
先上一段測試程式碼跟資源以及效果
#include "HelloWorldScene.h" #include "cocostudio/CocoStudio.h" #include "ui/CocosGUI.h" USING_NS_CC; using namespace cocostudio::timeline; Scene* HelloWorld::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); auto sp = Sprite::create("cocos-html5.png"); sp->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)); this->addChild(sp, 0); auto sprite1 = Sprite::create("cocos2dbanner.png"); sprite1->setPosition(Vec2(50,100)); sp->addChild(sprite1, 2); auto sprite2 = Sprite::create("powered.png"); sprite2->setPosition(Vec2(50,50)); sp->addChild(sprite2, -2); return true; }
資源
效果
我們首先建立一個精靈,然後向這個精靈中新增兩個精靈,一個zorder是正的,一個是負的,可以發現正的顯示在它的上面,負的顯示在它的下面。為什麼呢?
來看看node的visit方法:
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->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; }
這個方法中我們可以看到, 如果沒有子節點的情況下只會把自己給渲染出來,如果有子節點,那麼它會先根據其中的zOrder來從小到大排序,然後它先渲染小於0的子節點,再渲染它本身,最後渲染大於0的子節點,這個過程是遞迴的。由於後面渲染的是顯示在前面渲染的上面,所以,我們就不難理解得出這個結論:
一個節點的子節點,如果zorder是小於0,那麼顯示在這個節點的下面,否則顯示在上面;由於是遞迴的,子節點的子節點的顯示是相當於子節點而言的,並不影響這個節點。