虽然只有1个半月的cocos基础,但是我感觉我浑身充满了力量and power~~
进入正题, 现在我来大致谈下cocos2dx这款引擎。
1.cocos2dx是采用树形的方式和引用计数管理成员对象的,
引用计数:引用计数其实很简单,就是0的时候被释放,>=1的时候对象存在,通过addchild可以将参数的对象 添加到layer上。简单看下引擎代码:
void Node::addChild(Node *child, int zOrder, int tag)
{
CCASSERT( child != nullptr, "Argument must be non-nil");//断言判断child是否不为空指针,nullptr也是c++特性
CCASSERT( child->_parent == nullptr, "child already added. It can't be added again");
//_children 是个存放了node指针的vector容器,getchildren其实就是获得这个容器.
if (_children.empty())//如果当前vector没有对象的话,执行childrenalloc,为vector预留4个元素大小的空间
{
this->childrenAlloc();
}
this->insertChild(child, zOrder);//然后添加child,并设置层级,即zorder,在引擎树形遍历 的时候会将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);//node强转为场景添加到引擎world中去。
break;
}
}
#endif
child->_tag = tag;//tag默认为-1
child->setParent(this);//child的父对象为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)//颜色变化默认为false,action的时候用到
{
updateCascadeColor();
}
if (_cascadeOpacityEnabled)//透明度变化false,同上
{
updateCascadeOpacity();
}
}
其实这些还不是重点,主要看 this->insertChild(child, zOrder)这,进行了引用计数 ,在创建对象成功的时候引用计数为1,添加到场景之后引用计数为2,就是这个原因了:
void Node::insertChild(Node* child, int z)
{
_reorderChildDirty = true;
_children.pushBack(child);
child->_setLocalZOrder(z);
}
void pushBack(T object)
{
CCASSERT(object != nullptr, "The object should not be nullptr");
_data.push_back( object );
object->retain();//就是这里~
}
所以说,引用计数为1的只是说明创建了这个对象,是存在的,但是不以为着这个对象一定会在场景中显示的存在的。
又比如你创建了容器,存放sprite,方便以后调用std;:vector<Sprite*> _vec,那么你就改更加注意容器里面对象的引用计数了。
顺便提一下vector,不得不说太好用了,在我看来,vetor就像是一个动态数组。
你可以用sort对vector里面的对象进行排序,你可以v.pushback("heihei");添加元素。不过最好时刻关注你的内存,以及vector的capacity,因为vector的动态增长,是通过一段预留空间(reserve)实现的,而引擎内的cache类基本也都是用vector和map的衍生,当你添加过多缓存的时候,会发生一些预想不到的问题。
2.说一下我之前遇到过的一些问题:
Q:我用了cocostudio的scorlliview,我知道scollview内部有实现触摸机制,那么我在外部添加 onebyone即单点触控的时候为什么会感应不到?
R:这个大哥,问得好!这就涉及到触摸优先级的问题了,我可以告诉你scollview的优先级为0!而你外部添加的触摸事件增会大于0.那么这个时候你就需要修改优先级了:
listener=EventListenerTouchOneByOne::create();
listener->onTouchbegan=[&](Touch* touch,Event event){
CCLOG("touch");
return true;
};//&引用传递,=值传递,this即将当前对象传进去,这里用的是lambda.
_eventDispatcher->addEventListenerWithFixedPriority(listener,-1);//添加,并设置优先级为-1;
当前你也可以这样:
Director::getInstance()->getEventDispatcher()->setPriority(listener,-1);//
简单粗暴OK!
其实吧,之前我用了3.0final的时候就发现一个问题关于onkeyrelease:
void myUI::onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event)
{
if (keyCode==EventKeyboard::KeyCode::KEY_BACKSPACE)
{
Director::getInstance()->end();
}
}
发现,诶?!怎么点击了后退没反应??当时没解决,就做了另外一个按钮去关闭它。现在一想,可能是触摸优先级的事情~欢迎各位大哥大姐去尝试下~ps:本人目前用的是3.0beta2,为什么?因为懒~因为beta2可爱的ui创建工程~
2.spine的问题,如果我要在spine骨骼的手掌上实现武器的换装,怎么搞?
众所周知,skeleton并没有继承node,那么我们就无法直接在slot or bone上添加sprite,那么怎么办?改!
借鉴这位大神的一篇文章,就能很好的解决这个问题:
http://blog.csdn.net/n5/article/details/21795265
本人会陆续推出菜鸟也能学cocos一系列文章,每篇文章都会有俩个模块,1-讲下cocos引擎,2-提问和回答问题,有什么好的意见或者问题也可以在评论里面写出来。然后就是最重要的~,求收藏,求订阅,欢迎关注~
ps:本人果断菜鸟!如果有什么不对的,希望各位大神指出,互相进步~