cocos2d-x游戏开发(八)各类构造器

前端之家收集整理的这篇文章主要介绍了cocos2d-x游戏开发(八)各类构造器前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

欢迎转载: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()函数

  1. CCSprite*CCSprite::create()
  2. {
  3. CCSprite*pSprite=newCCSprite();//调用构造函数,产生对象
  4. if(pSprite&&pSprite->init())//创建对象成功并且其init函数返回true则添加自动释放池
  5. {
  6. pSprite->autorelease();
  7. returnpSprite;
  8. }
  9. CC_SAFE_DELETE(pSprite);//安全释放
  10. returnNULL;
  11. }

看到了,create函数里面实质上做了两件事:1.调用构造函数 2.init()成功则添加自动释放池。

然后看init()函数,就是自己的一些初始化工作了。

对于这个结构大家要非常熟悉,几乎可以说是一个套路。

这个二阶段构造用的很多,为了简化代码提高效率,cocos2d-x有个函数宏专门来干这个活:

?
    #defineCREATE_FUNC(__TYPE__)\
  1. static__TYPE__*create()\
  2. {\
  3. __TYPE__*pRet=new__TYPE__();\
  4. if(pRet&&pRet->init())\
  5. {\
  6. pRet->autorelease();\
  7. returnpRet;\
  8. }\
  9. else\
  10. deletepRet;\
  11. pRet=NULL;\
  12. returnNULL;\
  13. }

这个跟上面CCSprite的create函数很像啊。结构几乎是一样的。

所以我们自己的类只需要用这个宏定义,然后实现init()函数就可以了。用的时候直接调用create()函数

比如我写Ship:

?
    #ifndef__MoonWarriorsx__Ship__
  1. #define__MoonWarriorsx__Ship__
  2. #include"cocos2d.h"
  3. #include"UnitSprite.h"
  4. USING_NS_CC;
  5. classShip:publicUnitSprite{
  6. private:
  7. //速度
  8. intm_speed;
  9. //子弹速度
  10. intm_bulletSpeed;
  11. //生命值
  12. intm_HP;
  13. //子弹类型
  14. intm_bulletTypeValue;
  15. //子弹威力
  16. intm_bulletPowerValue;
  17. //是否在投掷炸弹
  18. boolm_throwBombing;
  19. //是否可被攻击
  20. boolm_canBeAttack;
  21. boolm_isThrowBomb;
  22. intm_zOder;
  23. //最大子弹威力
  24. intm_maxBulletPowerValue;
  25. //出现的初始位置
  26. CCPointm_appearPosition;
  27. intm_hurtColorLife;
  28. boolm_active;
  29. public:
  30. Ship();
  31. ~Ship();
  32. //被攻击使能
  33. voidmakeAttack(CCNode*pSender);
  34. //更新
  35. virtualvoidupdate(floatdt);
  36. //射击
  37. voidshoot(floatdt);
  38. //初始化
  39. virtualboolinit();
  40. //被攻击,受伤
  41. virtualvoidhurt();
  42. //销毁飞船
  43. virtualvoiddestroy();
  44. //获取生存状态
  45. virtualboolisActive();
  46. //碰撞矩形
  47. virtualCCRectcollideRect();
  48. intgetZoder();
  49. //构造器
  50. CREATE_FUNC(Ship);
  51. };
  52. #endif/*defined(__MoonWarriorsx__Ship__)*/

然后构造函数只带了一个初始化列表赋初值,没干别的事情。接着实现init()函数,所有初始化工作都在这里实现:

?
    boolShip::init()
  1. //superinitfirst
  2. if(!CCSprite::init())
  3. returnfalse;
  4. }
  5. //initlife
  6. CCTexture2D*shipTextureCache=CCTextureCache::sharedTextureCache()->addImage(s_ship01);
  7. CCRectrec=CCRectMake(0,60,38);
  8. this->initWithTexture(shipTextureCache,rec);
  9. this->setPosition(m_appearPosition);
  10. //setframe
  11. CCSpriteFrame*frame0=CCSpriteFrame::createWithTexture(shipTextureCache,CCRectMake(0,38));
  12. CCSpriteFrame*frame1=CCSpriteFrame::createWithTexture(shipTextureCache,CCRectMake(60,38));
  13. CCArray*animFrames=CCArray::create();
  14. animFrames->addObject(frame0);
  15. animFrames->addObject(frame1);
  16. //shipanimate
  17. //这个方法有差异
  18. CCAnimation*animation=CCAnimation::createWithSpriteFrames(animFrames,0.1);
  19. CCAnimate*animate=CCAnimate::create(animation);
  20. this->runAction(CCRepeatForever::create(animate));
  21. //子弹发射
  22. this->schedule(schedule_selector(Ship::shoot),0.16);
  23. //reviveeffect
  24. this->m_canBeAttack=false;
  25. 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};
  26. ghostSprite->setBlendFunc(cbl);
  27. ghostSprite->setScale(8);
  28. ghostSprite->setPosition(ccp(this->getContentSize().width/2,12));
  29. this->addChild(ghostSprite,3000,99999);
  30. ghostSprite->runAction(CCScaleTo::create(0.5,1,1));
  31. //闪烁动画
  32. CCBlink*blinks=CCBlink::create(3,9);
  33. //回调,攻击使能
  34. //带执行者回调,谁执行Action传谁。这里是this,所以传的就是this
  35. CCCallFuncN*makeBeAttack=CCCallFuncN::create(this,callfuncN_selector(Ship::makeAttack));
  36. this->runAction(CCSequence::create(CCDelayTime::create(0.5),blinks,makeBeAttack,NULL));
  37. returntrue;
  38. }

init函数要先调用super的init(),然后写自己的东西。

这样的二阶段构造有个好处,就是将自动释放封装起来了。因为这个create函数是个static的,创建对象成功且初始化成功就将其添加自动释放池,然后返回对象实例。你通过create获得对象后不用管它的释放问题。

当然,你也可以标新立异,不一定就按这个来。不过关键一点是,不管你怎么构造你的实例,要确保成功并将其加到自动释放池。比如我有个子弹类不是用create创建实例的,其使用如下:

?
    Bullet*bullet_a=newBullet(m_bulletSpeed,"W1.png",1);
  1. if(bullet_a){
  2. bullet_a->autorelease();//添加自动释放池
  3. play_bullet->addObject(bullet_a);
  4. this->getParent()->addChild(bullet_a,bullet_a->m_zorder,901);
  5. bullet_a->setPosition(ccp(position.x+offset,position.y+3+contentSize.height*0.3));
  6. }else{
  7. deletebullet_a;
  8. bullet_a=0;
  9. }

看,自己的构造函数,还要自己添加自动释放池。一看就很乱。其实这个也可以封装起来,自己实现create函数,不用那个宏定义,后续改下。


这里有一点不一样,就是CCScene的构造。

coco2d-x里面导演执行的单元是CCScene,就是场景。一个场景里面会添加很多CCLayer,即层。层里面又会添加很多元素,比如CCSprite,CCMenu等。那么场景如何构造呢?

demo里面是这一做的,在主Layer里面定义一个static的函数scene(),返回一个CCScene对象,例如:

?
    CCScene*HelloWorld::scene()
  1. //'scene'isanautoreleaSEObject
  2. CCScene*scene=CCScene::create();
  3. //'layer'isanautoreleaSEObject
  4. HelloWorld*layer=HelloWorld::create();
  5. //addlayerasachildtoscene
  6. scene->addChild(layer);
  7. //returnthescene
  8. returnscene;
  9. }

他在这个函数里面将主Layer构造出来,然后添加到场景里面。注意,所有create函数构造的对象都是一个autorelease的对象。

后执行场景:

?
    //createascene.it'sanautoreleaSEObject
  1. CCScene*pScene=HelloWorld::scene();
  2. //run
  3. pDirector->runWithScene(pScene);

看,封装好了,代码多清晰。


好了,就这么多,打完收工。

猜你在找的Cocos2d-x相关文章