【深入瞭解cocos2d-x 3.x】UI樹(1)——什麼是UI樹

近期在學習《我所理解的Cocos2d-x》這一本書,被作者深厚的功力所折服,感覺到自己實在是太弱了,cocos2d-x當中要學習的東西實在是太多了。

在《我所理解的cocos2d-x》中關於UI樹與內存管理其實是關聯性很強的,這一篇主要寫我對UI樹的理解。(本文基於cocos2d-x 3.2版本,其他版本API可能會有所變化)

首先得普及一下cocos2d-x的基礎概念,cocos2d-x的遊戲世界一般是由一個又一個的場景(Sence)組成的,比如登錄是一個場景,戰鬥是一個場景;然後場景之下分爲一個又一個的層(Layer),比如界面層,地圖層;層下又分爲一個又一個的精靈、UI控件以及各類的界面元素。而以上種種都是基於一個叫做Node的基類。好了,回顧完了。下面我們來看看這個Node究竟做了什麼(下面的聲明忽略的部分無關函數):

class CC_DLL Node : public Ref
{
public:
    ////// ADD //////
    virtual void addChild(Node * child);
    virtual void addChild(Node * child, int localZOrder);
    virtual void addChild(Node* child, int localZOrder, int tag);
    virtual void addChild(Node* child, int localZOrder, const std::string &name);

    ////// GET //////
    virtual Node * getChildByTag(int tag) const;
    virtual Node* getChildByName(const std::string& name) const;
    template <typename T>
    inline T getChildByName(const std::string& name) const { return static_cast<T>(getChildByName(name)); }
    virtual void enumerateChildren(const std::string &name, std::function<bool(Node* node)> callback) const;
    virtual Vector<Node*>& getChildren() { return _children; }
    virtual const Vector<Node*>& getChildren() const { return _children; }
    virtual ssize_t getChildrenCount() const;
    virtual Node* getParent() { return _parent; }
    virtual const Node* getParent() const { return _parent; }


    ////// REMOVES //////
    virtual void removeFromParent();
    virtual void removeFromParentAndCleanup(bool cleanup);
    virtual void removeChild(Node* child, bool cleanup = true);
    virtual void removeChildByTag(int tag, bool cleanup = true);
    virtual void removeChildByName(const std::string &name, bool cleanup = true);
    virtual void removeAllChildren();
    virtual void removeAllChildrenWithCleanup(bool cleanup);
}
可以看出大致分爲3類方法,第一個是addChild,作用是爲此節點添加子節點,當我們需要將一個精靈添加到層中時,我們可以這麼做

	Layer l = Layer::create();
	Sprite s = Sprite::create();
	l->addChild(s);
	this->addChild(l);

addChild還有其他的幾個變種,這裏就不多解釋了。addChild是UI樹的重要組成部分之一,它將一個節點添加到UI樹中,UI樹會保持對這個節點的強引用(關於內存部分,下篇文章會說到)。

第二個重要的方法是getXXX,相信用的人也挺多了,這裏就不多說了,着重說下新冒出來的吧,分別是:

    template <typename T>
    inline T getChildByName(const std::string& name) const { return static_cast<T>(getChildByName(name)); }
    virtual void enumerateChildren(const std::string &name, std::function<bool(Node* node)> callback) const;

第一個getChildByName<T>和普通的getChildByName其實差不多,看實現就知道了,只不過這個增加了一個模板,不用手動寫靜態轉換。使用方法也差不多,例如,我想要獲取到一個層下名字叫“exit”的精靈節點,就可以這麼用:

l->getChildByName<Sprite>("exit");
是不是稍微簡潔點?其實這種用法在Unity3D上已經非常常用了、

再說說另外一個函數enumerateChildren,這個函數就非常給力了,這個函數會搜索當前節點下的所有子節點,只要節點下的子節點的名字與參數name一致,就會執行第二個參數的回調函數callback(當然,這函數還不止那麼簡單)。這裏不做更多的分析(以後會單獨出一篇文章對這個函數進行具體的分析,這個函數也是一個非常有意思的函數啊,= =)

接下來的函數就是removeXXXX了,這個函數的作用就是從UI樹中移除某個節點,例如removeFromParent就是從UI數中將自己從父節點中移除。removeChild就是將參數中的子節點從UI樹中移除。


OK,基本函數已經介紹完畢;下面來說說UI樹的組成。一般而言,Scene就是UI樹的根節點,而Layer節點一般作爲Scene下的節點,Layer可以嵌套Layer;Layer也有許多變種,例如LayerColor。Layer上可以添加各種圖片以及控件,這些圖片和控件上也可以添加各類子節點,由於所有的這些的基類都是Node,所以添加起來非常自由,但是需要記住的是,雖然可以把Layer添加到一個Sprite上,但是這是一個在正常需求下不太合乎邏輯的事情。

上述基本就是cocos2d-x 3.x引擎的UI樹系統,合理的使用這個UI樹系統將會加快遊戲開發的進度以及提高遊戲的穩定性。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章