欢迎转载: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()函数
[cpp] view plain copy print ? @H_301_41@CCSprite*CCSprite::create() { CCSprite*pSprite=new@H_301_41@CCSprite();@H_502_55@//调用构造函数,产生对象@H_301_41@ if@H_301_41@(pSprite&&pSprite->init())//创建对象成功并且其init函数返回true则添加到自动释放池@H_301_41@ { pSprite->autorelease(); return@H_301_41@pSprite; } CC_SAFE_DELETE(pSprite);//安全释放@H_301_41@ return@H_301_41@NulL; }
看到了,create函数里面实质上做了两件事:1.调用构造函数 2.init()成功则添加到自动释放池。
然后看init()函数,就是自己的一些初始化工作了。
对于这个结构大家要非常熟悉,几乎可以说是一个套路。
这个二阶段构造用的很多,为了简化代码提高效率,cocos2d-x有个函数宏专门来干这个活:
? #defineCREATE_FUNC(__TYPE__)\@H_301_41@ static@H_301_41@__TYPE__*create()\ {\ __TYPE__*pRet=new@H_301_41@__TYPE__();\ if@H_301_41@(pRet&&pRet->init())\ {\ pRet->autorelease();\ return@H_301_41@pRet;\ }\ else@H_301_41@\ delete@H_301_41@pRet;\ pRet=NulL;\ return@H_301_41@NulL;\ }
这个跟上面CCSprite的create函数很像啊。结构几乎是一样的。
所以我们自己的类只需要用这个宏定义,然后实现init()函数就可以了。用的时候直接调用create()函数。
比如我写Ship:
? #ifndef__MoonWarriorsx__Ship__@H_301_41@ #define__MoonWarriorsx__Ship__@H_301_41@ #include"cocos2d.h"@H_301_41@ #include"UnitSprite.h"@H_301_41@ USING_NS_CC; class@H_301_41@Ship:public@H_301_41@UnitSprite{ private@H_301_41@: //速度@H_301_41@ int@H_301_41@m_speed; //子d速度@H_301_41@ int@H_301_41@m_bulletSpeed; //生命值@H_301_41@ int@H_301_41@m_HP; //子d类型@H_301_41@ int@H_301_41@m_bulletTypeValue; //子d威力@H_301_41@ int@H_301_41@m_bulletPowerValue; //是否在投掷炸d@H_301_41@ bool@H_301_41@m_throwBombing; //是否可被攻击@H_301_41@ bool@H_301_41@m_canBeAttack; bool@H_301_41@m_isThrowBomb; int@H_301_41@m_zOder; //最大子d威力@H_301_41@ int@H_301_41@m_maxBulletPowerValue; //出现的初始位置@H_301_41@ CCPointm_appearposition; int@H_301_41@m_hurtcolorlife; bool@H_301_41@m_active; public@H_301_41@: Ship(); ~Ship(); //被攻击使能@H_301_41@ voID@H_301_41@makeAttack(CCNode*pSender); //更新@H_301_41@ virtual@H_301_41@voID@H_301_41@update(float@H_301_41@dt); //射击@H_301_41@ voID@H_301_41@shoot(float@H_301_41@dt); //初始化@H_301_41@ virtual@H_301_41@bool@H_301_41@init(); //被攻击,受伤@H_301_41@ virtual@H_301_41@voID@H_301_41@hurt(); //销毁飞船@H_301_41@ virtual@H_301_41@voID@H_301_41@destroy(); //获取生存状态@H_301_41@ virtual@H_301_41@bool@H_301_41@isActive(); //碰撞矩形@H_301_41@ virtual@H_301_41@CCRectcollIDeRect(); int@H_301_41@getZoder(); //构造器@H_301_41@ CREATE_FUNC(Ship); }; #endif/*defined(__MoonWarriorsx__Ship__)*/@H_301_41@
然后构造函数只带了一个初始化列表赋初值,没干别的事情。接着实现init()函数,所有初始化工作都在这里实现:
? @H_403_658@bool@H_301_41@Ship::init() //superinitfirst@H_301_41@ if@H_301_41@(!CCSprite::init()) return@H_301_41@false@H_301_41@; } //initlife@H_301_41@ CCTexture2D*shipTextureCache=CCTextureCache::sharedTextureCache()->addImage(s_ship01); CCRectrec=CCRectMake(0,60,38); this@H_301_41@->initWithTexture(shipTextureCache,rec); this@H_301_41@->setposition(m_appearposition); //setframe@H_301_41@ 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@H_301_41@ //这个方法有差异@H_301_41@ CCAnimation*animation=CCAnimation::createWithSpriteFrames(animFrames,0.1); CCAnimate*animate=CCAnimate::create(animation); this@H_301_41@->runAction(CCRepeatForever::create(animate)); //子d发射@H_301_41@ this@H_301_41@->schedule(schedule_selector(Ship::shoot),0.16); //reviveeffect@H_301_41@ this@H_301_41@->m_canBeAttack=false@H_301_41@; 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@H_301_41@->getContentSize().wIDth/2,12)); this@H_301_41@->addChild(ghostSprite,3000,99999); ghostSprite->runAction(CCScaleto::create(0.5,1,1)); //闪烁动画@H_301_41@ CCBlink*blinks=CCBlink::create(3,9); //回调,攻击使能@H_301_41@ //带执行者回调,谁执行Action传谁。这里是this,所以传的就是this@H_301_41@ CCCallFuncN*makeBeAttack=CCCallFuncN::create(this@H_301_41@,callfuncN_selector(Ship::makeAttack)); this@H_301_41@->runAction(CCSequence::create(CCDelayTime::create(0.5),blinks,makeBeAttack,NulL)); return@H_301_41@true@H_301_41@; }
init函数要先调用super的init(),然后写自己的东西。
这样的二阶段构造有个好处,就是将自动释放封装起来了。因为这个create函数是个static的,创建对象成功且初始化成功就将其添加到自动释放池,然后返回对象实例。你通过create获得对象后不用管它的释放问题。
当然,你也可以标新立异,不一定就按这个来。不过关键一点是,不管你怎么构造你的实例,要确保成功并将其加到自动释放池。比如我有个子d类不是用create创建实例的,其使用如下:
? @H_301_41@Bullet*bullet_a=new@H_301_41@Bullet(m_bulletSpeed,"W1.png"@H_301_41@,1); if@H_301_41@(bullet_a){ bullet_a->autorelease();//添加到自动释放池@H_301_41@ play_bullet->addobject(bullet_a); this@H_301_41@->getParent()->addChild(bullet_a,bullet_a->m_zorder,901); bullet_a->setposition(ccp(position.x+offset,position.y+3+contentSize.height*0.3)); }else@H_301_41@{ delete@H_301_41@bullet_a; bullet_a=0; }
看,自己的构造函数,还要自己添加自动释放池。一看就很乱。其实这个也可以封装起来,自己实现create函数,不用那个宏定义,后续改下。
这里有一点不一样,就是CCScene的构造。
coco2d-x里面导演执行的单元是CCScene,就是场景。一个场景里面会添加很多cclayer,即层。层里面又会添加很多元素,比如CCSprite,Ccmenu等。那么场景如何构造呢?
demo里面是这一做的,在主Layer里面定义一个static的函数scene(),返回一个CCScene对象,例如:
? @H_301_41@CCScene*HelloWorld::scene() //'scene'isanautoreleaSEObject@H_301_41@ CCScene*scene=CCScene::create(); //'layer'isanautoreleaSEObject@H_301_41@ HelloWorld*layer=HelloWorld::create(); //addlayerasachildtoscene@H_301_41@ scene->addChild(layer); //returnthescene@H_301_41@ return@H_301_41@scene; }
他在这个函数里面将主Layer构造出来,然后添加到场景里面。注意,所有create函数构造的对象都是一个autorelease的对象。
然后执行场景:
? //createascene.it'sanautoreleaSEObject@H_301_41@ CCScene*pScene=HelloWorld::scene(); //run@H_301_41@ pDirector->runWithScene(pScene);
看,封装好了,代码多清晰。
好了,就这么多,打完收工。
总结以上是内存溢出为你收集整理的cocos2d-x游戏开发(八)各类构造器全部内容,希望文章能够帮你解决cocos2d-x游戏开发(八)各类构造器所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)