标签:des blog io color ar os 使用 sp for
class CC_DLL Node : public Ref
因此NODE可以直接使用aurelease方法实现自动内存管理
什么是锚点呢?有过动画制作经验的同学可能了解,在这里小鱼简单提一下,锚点通俗一点理解就是图形在做变形,旋转时候的一个基准点,比如上面的一些gif图形进行x,y轴方向变换时的原点就是它的锚点,上面所有图的锚点都是左下角,这也是cocos2d-x默认的锚点位置。
node的有些成员如下,非常重要
int _localZOrder; ///< Local order (relative to its siblings) used to sort the node float _globalZOrder; ///< Global order used to sort the node Vector<Node*> _children; ///< array of children nodes Node *_parent; ///< weak reference to parent node int _tag; ///可以给当前的Node对象定义一个 int类型的标识 std::string _name; ///可以给当前Node对象起一个字符串类型的名称。
这几个变量说明Node是一个树的数据结构,除非是根否则每个node对象都有父结点, _parent,每个Node还有一系列子结点 _children 这些子结点用了一个 Vector来存放,并且每个Node对象都有同级子结点(同一个父亲的子结点)的一个Z轴方向的顺序_localZOrder,在在游戏开发中有一个名词叫做深度排序,类似这个意思。
还有一个变量_globalZOrder这是全局的一个深度排序,当localorder相同的时候,根据globalorder进行排列
void Node::addChild(Node *child, int zOrder, int tag) { CCASSERT( child != nullptr, "Argument must be non-nil"); CCASSERT( child->_parent == nullptr, "child already added. It can‘t be added again"); if (_children.empty()) { this->childrenAlloc(); } this->insertChild(child, zOrder); #if CC_USE_PHYSICS if (child->getPhysicsBody() != nullptr) { child->getPhysicsBody()->setPosition(this->convertToWorldSpace(child->getPosition())); } for (Node* node = this->getParent(); node != nullptr; node = node->getParent()) { if (dynamic_cast<Scene*>(node) != nullptr) { (dynamic_cast<Scene*>(node))->addChildToPhysicsWorld(child); break; } } #endif child->_tag = tag; child->setParent(this); child->setOrderOfArrival(s_globalOrderOfArrival++); if( _running ) { child->onEnter(); // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter if (_isTransitionFinished) { child->onEnterTransitionDidFinish(); } } if (_cascadeColorEnabled) { updateCascadeColor(); } if (_cascadeOpacityEnabled) { updateCascadeOpacity(); } }
先判断了当前结点是的子结点列表是否为空,如果 是空调用了Node类的成员函数 childrenAlloc(); 分配了内存。
然后调用了
this->insertChild(child, zOrder);
这个函数是根据zOrder的顺序将child加入到当前结点的子结点列表里面,我们跟进这个函数看看是怎么实现的。
void Node::insertChild(Node* child, int z) { _reorderChildDirty = true; _children.pushBack(child); child->_setLocalZOrder(z); }
这个insertChild并没有将 _children这个vecort的顺序重新排列,只是将child这个对象加到了_children 列表的最后面。还做了改child的zOrder的设置操作。
注意到这里使用了_reorderChildDirty 这个变量,命名上理解,这个变量是标记着,当前Node对象的子对象列表是否需要重新排列操作,这里的设计很巧妙,在insertChild的时候不必排列一遍结点顺序,小鱼猜,肯定在使用这个结点的时候会根据_reorderChildDirty 这个变量的值来决定这个结点是否需要排列一遍子结点的顺序。于是我在Node类定义中找到了这样的一个方法。
void Node::sortAllChildren() { if( _reorderChildDirty ) { std::sort( std::begin(_children), std::end(_children), nodeComparisonLess ); _reorderChildDirty = false; } }
在running状态下,新加入的子结点会调用一个 onEnter函数,前面提到过,Node类定义了一些事件,这个onEnter就是其中的一个事件,从代码上直接可以理解这个onEnter事件的含义是,当结点被加入到正在运行的结点后就会触发的一个回调函数。
if (_isTransitionFinished) { child->onEnterTransitionDidFinish(); }
if (_cascadeColorEnabled) { updateCascadeColor(); } if (_cascadeOpacityEnabled) { updateCascadeOpacity(); }
这两个变量是标记是否继承父结点的颜色与透明度如果父结点定义了要子结点继承它的颜色与透明设置那么会递归的更新每个子结点的颜色与透明度与父结点一样。
到此,这个addChild方法我们已经看明白了,关于物理方面的东西先放到一边,从后章节我们来分析。
下面我们看一下Node类最重要的一个创建对象方法create方法
Node * Node::create(void) { Node * ret = new Node(); if (ret && ret->init()) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } return ret; }
这个create方法很简单,
1. new一个Node对象
2. 调用Node的init方法进行初始化。
3. 设置Node 为自动内存释放。
Cocos2d-x推荐我们作用create方法来创建结点,而不要用new的方式创建。我们在应用的时候应该尊重这条建议。
create方法里面提供到了一个init方法,下面我们跟进源码,看一下init都干了些什么。
virtual bool init(); bool Node::init() { return true; }
看到了这么干净的init方法,里面就一行代码。怎么回事呢?
我们看一下init方法的声明为 virtual 所以这个方法是给它的子类使用的,不同的子类有不同的init过程 所以这里只是预留了一个初始化的接口,在你的类中如果有自己的特殊的初始化过程那么重载这个init就可以了。
从命名上理解,_isTransitionfinished 是一个标记着Node对象是否做完了变换的一个状态,这里触发了事件的回调函数
node结点具体怎么来渲染使用的是 draw方法,
如果要显示一个node结点及其子结点那么我们就要使用visit方法,这样可以递归的按照zOrder顺序地draw每一个子结点。
标签:des blog io color ar os 使用 sp for
原文地址:http://www.cnblogs.com/notlate/p/4103729.html