Node
Node
常用子类包括Scene, Layer, Widget
等,常用属性有旋转(float _rotationX, float _rotationY
)、伸缩(float _scaleX, float _scaleY
)、位置(Vec2 _position
)、倾斜(float _skewX, float _skewY
)、锚点(Vec2 _anchorPoint
)、大小(Size _contentSize
)、全局层级(float _globalZOrder
)和可见性(bool _visible
)等,支持添加子节点(addChild, removeChild
),使用定时器(schedule, unschedule
),执行动画(runAction, stopAction
)等操作。
-
生命周期:
子类重写以下方法时必须显示调用父类对应的方法。
init()
:初始化节点时调用。onEnter()
:进入节点时调用。onEnterTransitionDidFinish()
:进入节点而且过渡动画结束时候调用。update(float delta)
:如果想要每帧执行Update方法,必须先调用scheduleUpdate
方法。只重写Update
是无法生效的。onExit()
:退出节点时候调用。onExitTransitionDidStart()
:退出节点而且开始过渡动画时候调用。cleanup()
:节点对象被清除时候调用。
从源码上可以确定以下几点:
- 当运行中的节点新增子节点时,子节点会立即执行
OnEnter
和onEnterTransitionDidFinish
。/** * Adds a child to the container with z-order as 0. * If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. * @param child A child node. */ virtual void addChild(Node * child);
- 设置下一个场景的流程:
void Director::setNextScene() { _eventDispatcher->dispatchEvent(_beforeSetNextScene); bool runningIsTransition = dynamic_cast<TransitionScene*>(_runningScene) != nullptr; bool newIsTransition = dynamic_cast<TransitionScene*>(_nextScene) != nullptr; // If it is not a transition, call onExit/cleanup if (! newIsTransition) { if (_runningScene) { _runningScene->onExitTransitionDidStart(); _runningScene->onExit(); } // issue #709. the root node (scene) should receive the cleanup message too // otherwise it might be leaked. if (_sendCleanupToScene && _runningScene) { _runningScene->cleanup(); } } if (_runningScene) { _runningScene->release(); } _runningScene = _nextScene; _nextScene->retain(); _nextScene = nullptr; if ((! runningIsTransition) && _runningScene) { _runningScene->onEnter(); _runningScene->onEnterTransitionDidFinish(); } _eventDispatcher->dispatchEvent(_afterSetNextScene); }
- 设置通知节点(独立绘制的节点,不随场景切换而消失)的流程:
如果想要删除通知节点可以直接使用void Director::setNotificationNode(Node *node) { if (_notificationNode != nullptr){ _notificationNode->onExitTransitionDidStart(); _notificationNode->onExit(); _notificationNode->cleanup(); } CC_SAFE_RELEASE(_notificationNode); _notificationNode = node; if (node == nullptr) return; _notificationNode->onEnter(); _notificationNode->onEnterTransitionDidFinish(); CC_SAFE_RETAIN(_notificationNode); }
Director->getInstance()->setNotificationNode(nullptr)
。
-
层级
Node
使用三种层级globalZOrder, localZOrder和orderOfArrival来标记渲染顺序,优先级依次递减,层级越大越后渲染,视觉上处于越上层。class Node(Ref) { protected: #if CC_LITTLE_ENDIAN union { struct { std::uint32_t _orderOfArrival; std::int32_t _localZOrder; }; std::int64_t _localZOrder$Arrival; }; #else union { struct { std::int32_t _localZOrder; std::uint32_t _orderOfArrival; }; std::int64_t _localZOrder$Arrival; }; #endif float _globalZOrder; ///< Global order used to sort the node }
_globalZOrder
:标识全局的层级,默认值为0,Node
提供了对应的set方法和get方法。/** Defines the order in which the nodes are renderer. Nodes that have a Global Z Order lower, are renderer first. In case two or more nodes have the same Global Z Order, the order is not guaranteed. The only exception if the Nodes have a Global Z Order == 0. In that case, the Scene Graph order is used. By default, all nodes have a Global Z Order = 0. That means that by default, the Scene Graph order is used to render the nodes. Global Z Order is useful when you need to render nodes in an order different than the Scene Graph order. Limitations: Global Z Order can't be used by Nodes that have SpriteBatchNode as one of their ancestors. And if ClippingNode is one of the ancestors, then "global Z order" will be relative to the ClippingNode. @see `setLocalZOrder()` @see `setVertexZ()` @since v3.0 * * @param globalZOrder The global Z order value. */ virtual void setGlobalZOrder(float globalZOrder); /** * Returns the Node's Global Z Order. * * @see `setGlobalZOrder(int)` * * @return The node's global Z order */ virtual float getGlobalZOrder() const { return _globalZOrder; }
_localZOrder
:标识同一个父节点下子节点的层级,默认值为0。同样Node
提供了相应的get方法和set方法,并且可以在调用addChild
方法时指定_localZOrder
。场景图(节点树)的遍历遵循中序遍历算法,_localZOrder < 0
的节点定义为左子树,_localZOrder >= 0
的节点定义为右子树,也就是说先渲染左子树的节点,再渲染根节点,最后渲染右子树的节点。/** LocalZOrder is the 'key' used to sort the node relative to its siblings. The Node's parent will sort all its children based on the LocalZOrder value. If two nodes have the same LocalZOrder, then the node that was added first to the children's array will be in front of the other node in the array. Also, the Scene Graph is traversed using the "In-Order" tree traversal algorithm ( http://en.wikipedia.org/wiki/Tree_traversal#In-order ) And Nodes that have LocalZOrder values < 0 are the "left" subtree While Nodes with LocalZOrder >=0 are the "right" subtree. @see `setGlobalZOrder` @see `setVertexZ` * * @param localZOrder The local Z order value. */ virtual void setLocalZOrder(std::int32_t localZOrder); /** * Gets the local Z order of this node. * * @see `setLocalZOrder(int)` * * @return The local (relative to its siblings) Z order. */ virtual std::int32_t getLocalZOrder() const { return _localZOrder; } /** * Adds a child to the container with a local z-order. * * If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. * * @param child A child node. * @param localZOrder Z order for drawing priority. Please refer to `setLocalZOrder(int)`. */ virtual void addChild(Node * child, int localZOrder);
_orderOfArrival
:按到达(加入到场景图)的顺序去标识渲染的顺序。当_globalZOrder
和_localZOrder
都相等时,越晚加入到场景图中的节点,就越后渲染。
-
常用子类
Scene
:自定义场景的父类(抽象类),对场景进行渲染等操作。/** @class Scene * @brief Scene is a subclass of Node that is used only as an abstract concept. Scene and Node are almost identical with the difference that Scene has its anchor point (by default) at the center of the screen. For the moment Scene has no other logic than that, but in future releases it might have additional logic. It is a good practice to use a Scene as the parent of all your nodes. Scene will create a default camera for you. */ class CC_DLL Scene : public Node
Layer
:Menu
继承自Layer
,提供触摸事件响应。/** @class Layer * @brief Layer is a subclass of Node that implements the TouchEventsDelegate protocol. All features from Node are valid, plus the following new features: - It can receive iPhone Touches - It can receive Accelerometer input */ class CC_DLL Layer : public Node
Widget
:cocos3.0的CocosUI.h
下的组件(e.g.Button
)都是继承自Widget
,提供窗口ui的交互。/** * @brief Base class for all ui widgets. * This class inherent from `ProtectedNode` and `LayoutParameterProtocol`. * If you want to implements your own ui widget, you should subclass it. */ class CC_GUI_DLL Widget : public ProtectedNode, public LayoutParameterProtocol
【参考资料】
[1] Cocos2D-X游戏开发技术精解 - 第3章 渲染框架
[2] [Cocos2d-X之触摸事件
[3] cocos2dx——节点的渲染(绘制)顺序LocalZOrder、GlobalZOrder、OrderOfArrival_break;的博客-优快云博客