欢迎转载:http://blog.csdn.net/fylz1125/article/details/8521997
这篇写cocos2d-x的构造器。
cocos2d-x引入自动释放机制后,创建的对象就不需要我们像C++编程那样自己delete了。但是怎么让自己的类也能保持cocos2d-x的风格呢?或者说怎么样才能让自己的类实例也能自动释放。
在cocos2d-x里面大量用到了一个叫create()方法(2.1.0版本)。几乎所有的实体类都会用这个create函数来产生实例而不是他们的构造函数。
看看CCSprite的create()函数
- CCSprite*CCSprite::create()
- {
- CCSprite*pSprite=newCCSprite();
- if(pSprite&&pSprite->init())
- {
- pSprite->autorelease();
- returnpSprite;
- }
- CC_SAFE_DELETE(pSprite);
- returnNULL;
- }
看到了,create函数里面实质上做了两件事:1.调用构造函数 2.init()成功则添加到自动释放池。
然后看init()函数,就是自己的一些初始化工作了。
对于这个结构大家要非常熟悉,几乎可以说是一个套路。
这个二阶段构造用的很多,为了简化代码提高效率,cocos2d-x有个函数宏专门来干这个活:
#defineCREATE_FUNC(__TYPE__)
- static__TYPE__*create()
- {
- __TYPE__*pRet=new__TYPE__();
- if(pRet&&pRet->init())
- {
- pRet->autorelease();
- returnpRet;
- }
- else
- deletepRet;
- pRet=NULL;
- returnNULL;
- }
这个跟上面CCSprite的create函数很像啊。结构几乎是一样的。
所以我们自己的类只需要用这个宏定义,然后实现init()函数就可以了。用的时候直接调用create()函数。
比如我写Ship:
#ifndef__MoonWarriorsx__Ship__
- #define__MoonWarriorsx__Ship__
-
- #include"cocos2d.h"
- #include"UnitSprite.h"
- USING_NS_CC;
- classShip:publicUnitSprite{
- private:
-
- intm_speed;
-
-
- intm_bulletSpeed;
- //生命值
- intm_HP;
- //子弹类型
- intm_bulletTypeValue;
- //子弹威力
- intm_bulletPowerValue;
- //是否在投掷炸弹
- boolm_throwBombing;
- //是否可被攻击
- boolm_canBeAttack;
- boolm_isThrowBomb;
- intm_zOder;
- //最大子弹威力
- intm_maxBulletPowerValue;
- //出现的初始位置
- CCPointm_appearPosition;
- intm_hurtColorLife;
- boolm_active;
- public:
- Ship();
- ~Ship();
- //被攻击使能
- voidmakeAttack(CCNode*pSender);
- //更新
- virtualvoidupdate(floatdt);
- //射击
- voidshoot(floatdt);
- //初始化
- virtualboolinit();
- //被攻击,受伤
- virtualvoidhurt();
- //销毁飞船
- virtualvoiddestroy();
- //获取生存状态
- virtualboolisActive();
- //碰撞矩形
- virtualCCRectcollideRect();
- intgetZoder();
- //构造器
- CREATE_FUNC(Ship);
- };
- #endif/*defined(__MoonWarriorsx__Ship__)*/
然后构造函数只带了一个初始化列表赋初值,没干别的事情。接着实现init()函数,所有初始化工作都在这里实现:
boolShip::init()
- //superinitfirst
- if(!CCSprite::init())
- returnfalse;
- }
- //initlife
- CCTexture2D*shipTextureCache=CCTextureCache::sharedTextureCache()->addImage(s_ship01);
- CCRectrec=CCRectMake(0,60,38);
- this->initWithTexture(shipTextureCache,rec);
- this->setPosition(m_appearPosition);
- //setframe
- CCSpriteFrame*frame0=CCSpriteFrame::createWithTexture(shipTextureCache,CCRectMake(0,38));
- CCSpriteFrame*frame1=CCSpriteFrame::createWithTexture(shipTextureCache,CCRectMake(60,38));
- CCArray*animFrames=CCArray::create();
- animFrames->addObject(frame0);
- animFrames->addObject(frame1);
- //shipanimate
- //这个方法有差异
- CCAnimation*animation=CCAnimation::createWithSpriteFrames(animFrames,0.1);
- CCAnimate*animate=CCAnimate::create(animation);
- this->runAction(CCRepeatForever::create(animate));
- //子弹发射
- this->schedule(schedule_selector(Ship::shoot),0.16);
- //reviveeffect
- this->m_canBeAttack=false;
- CCSprite*ghostSprite=CCSprite::createWithTexture(shipTextureCache,45,153); list-style:decimal-leading-zero outside; color:inherit; line-height:20px; margin:0px!important; padding:0px 3px 0px 10px!important"> ccBlendFunccbl={GL_SRC_ALPHA,GL_ONE};
- ghostSprite->setBlendFunc(cbl);
- ghostSprite->setScale(8);
- ghostSprite->setPosition(ccp(this->getContentSize().width/2,12));
- this->addChild(ghostSprite,3000,99999);
- ghostSprite->runAction(CCScaleTo::create(0.5,1,1));
- //闪烁动画
- CCBlink*blinks=CCBlink::create(3,9);
- //回调,攻击使能
- //带执行者回调,谁执行Action传谁。这里是this,所以传的就是this
- CCCallFuncN*makeBeAttack=CCCallFuncN::create(this,callfuncN_selector(Ship::makeAttack));
- this->runAction(CCSequence::create(CCDelayTime::create(0.5),blinks,makeBeAttack,NULL));
- returntrue;
- }
init函数要先调用super的init(),然后写自己的东西。
这样的二阶段构造有个好处,就是将自动释放封装起来了。因为这个create函数是个static的,创建对象成功且初始化成功就将其添加到自动释放池,然后返回对象实例。你通过create获得对象后不用管它的释放问题。
当然,你也可以标新立异,不一定就按这个来。不过关键一点是,不管你怎么构造你的实例,要确保成功并将其加到自动释放池。比如我有个子弹类不是用create创建实例的,其使用如下:
Bullet*bullet_a=newBullet(m_bulletSpeed,"W1.png",1);
- if(bullet_a){
- bullet_a->autorelease();
- play_bullet->addObject(bullet_a);
- this->getParent()->addChild(bullet_a,bullet_a->m_zorder,901);
- bullet_a->setPosition(ccp(position.x+offset,position.y+3+contentSize.height*0.3));
- }else{
- deletebullet_a;
- bullet_a=0;
- }
看,自己的构造函数,还要自己添加自动释放池。一看就很乱。其实这个也可以封装起来,自己实现create函数,不用那个宏定义,后续改下。
这里有一点不一样,就是CCScene的构造。
coco2d-x里面导演执行的单元是CCScene,就是场景。一个场景里面会添加很多CCLayer,即层。层里面又会添加很多元素,比如CCSprite,CCMenu等。那么场景如何构造呢?
demo里面是这一做的,在主Layer里面定义一个static的函数scene(),返回一个CCScene对象,例如:
CCScene*HelloWorld::scene()
- //'scene'isanautoreleaSEObject
- CCScene*scene=CCScene::create();
- //'layer'isanautoreleaSEObject
- HelloWorld*layer=HelloWorld::create();
- //addlayerasachildtoscene
- scene->addChild(layer);
- //returnthescene
- returnscene;
- }
他在这个函数里面将主Layer构造出来,然后添加到场景里面。注意,所有create函数构造的对象都是一个autorelease的对象。
然后执行场景:
//createascene.it'sanautoreleaSEObject
- CCScene*pScene=HelloWorld::scene();
- //run
- pDirector->runWithScene(pScene);
看,封装好了,代码多清晰。
好了,就这么多,打完收工。 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|