欢迎转载: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 plaincopyprint?

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

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

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

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

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

[cpp] view plaincopyprint?

  1. #define CREATE_FUNC(__TYPE__) \
  2. static __TYPE__* create() \
  3. { \
  4. __TYPE__ *pRet = new __TYPE__(); \
  5. if (pRet && pRet->init()) \
  6. { \
  7. pRet->autorelease(); \
  8. return pRet; \
  9. } \
  10. else \
  11. { \
  12. delete pRet; \
  13. pRet = NULL; \
  14. return NULL; \
  15. } \
  16. }

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

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

比如我写Ship:

[cpp] view plaincopyprint?

  1. #ifndef __MoonWarriorsx__Ship__
  2. #define __MoonWarriorsx__Ship__
  3. #include "cocos2d.h"
  4. #include "UnitSprite.h"
  5. USING_NS_CC;
  6. class Ship : public UnitSprite{
  7. private:
  8. // 速度
  9. int m_speed;
  10. // 子弹速度
  11. int m_bulletSpeed;
  12. // 生命值
  13. int m_HP;
  14. // 子弹类型
  15. int m_bulletTypeValue;
  16. // 子弹威力
  17. int m_bulletPowerValue;
  18. // 是否在投掷炸弹
  19. bool m_throwBombing;
  20. // 是否可被攻击
  21. bool m_canBeAttack;
  22. bool m_isThrowBomb;
  23. int m_zOder;
  24. // 最大子弹威力
  25. int m_maxBulletPowerValue;
  26. // 出现的初始位置
  27. CCPoint m_appearPosition;
  28. int m_hurtColorLife;
  29. bool m_active;
  30. public:
  31. Ship();
  32. ~Ship();
  33. // 被攻击使能
  34. void makeAttack(CCNode *pSender);
  35. // 更新
  36. virtual void update(float dt);
  37. // 射击
  38. void shoot(float dt);
  39. // 初始化
  40. virtual bool init();
  41. // 被攻击,受伤
  42. virtual void hurt();
  43. // 销毁飞船
  44. virtual void destroy();
  45. // 获取生存状态
  46. virtual bool isActive();
  47. // 碰撞矩形
  48. virtual CCRect collideRect();
  49. int getZoder();
  50. // 构造器
  51. CREATE_FUNC(Ship);
  52. };
  53. #endif /* defined(__MoonWarriorsx__Ship__) */

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

[cpp] view plaincopyprint?

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

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

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

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

[cpp] view plaincopyprint?

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

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

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

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

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

[cpp] view plaincopyprint?

  1. CCScene* HelloWorld::scene()
  2. {
  3. // 'scene' is an autorelease object
  4. CCScene *scene = CCScene::create();
  5. // 'layer' is an autorelease object
  6. HelloWorld *layer = HelloWorld::create();
  7. // add layer as a child to scene
  8. scene->addChild(layer);
  9. // return the scene
  10. return scene;
  11. }

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

然后执行场景:

[cpp] view plaincopyprint?

  1. // create a scene. it's an autorelease object
  2. CCScene *pScene = HelloWorld::scene();
  3. // run
  4. pDirector->runWithScene(pScene);

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

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

【转】cocos2d-x游戏开发(八)各类构造器的更多相关文章

  1. iOS cocos2d 2游戏开发实战(第3版)书评

    2013是游戏爆发的一年,手游用户也是飞速暴增.虽然自己不做游戏,但也是时刻了解手机应用开发的新动向.看到CSDN的"写书评得技术图书赢下载分"活动,就申请了一本<iOS c ...

  2. [Android游戏开发]八款开源 Android 游戏引擎 (巨好的资源)

    初学Android游戏开发的朋友,往往会显得有些无所适从,他们常常不知道该从何处入手,每当遇到自己无法解决的难题时,又往往会一边羡慕于 iPhone下有诸如Cocos2d-iphone之类的免费游戏引 ...

  3. (转载)如何学好iphone游戏开发

    转自:http://www.cnblogs.com/zilongshanren/archive/2011/09/19/2181558.html 自从发布<如何学习iphone游戏开发>到 ...

  4. 【Cocos2D研究院之游戏开发】

    http://www.xuanyusong.com/archives/category/ios/cocos2d_game 分类目录归档:[Cocos2D研究院之游戏开发]   201211-19 Co ...

  5. 《MFC游戏开发》笔记八 游戏特效的实现(二):粒子系统

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9360993 作者:七十一雾央 新浪微博:http:// ...

  6. cocos2d 游戏开发实战

    文章转自:http://uliweb.clkg.org/tutorial/read/40 6   cocos2d 游戏开发实战 6.1   创建cocos2d项目 6.2   cocos2d v3 & ...

  7. Html5 Egret游戏开发 成语大挑战(八)一般性二级页面处理

    在游戏中,我们一般会有各种各样的二级页面,比如游戏暂停界面或者游戏结束界面,这些界面组成了对玩家交互主要手段,在游戏开发中,对于这些界面的coding组织是非常有学问的,如果倒退到十年前,游戏开发的老 ...

  8. 【python游戏编程之旅】第八篇---pygame游戏开发常用数据结构

    本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 上一个博客我们一起学习了pygame中冲突检测技术:http://www.cnblogs.com/msxh/ ...

  9. 学习手机游戏开发的两个方向 Cocos2d-x 和 Unity 3D/2D,哪个前景更好?

    如题! 首先说一说学习手机游戏(移动游戏)这件事. 眼下移动互联网行业的在以井喷状态发展.全球几十亿人都持有智能终端设备(ios android),造就了非常多移动互联网创业机会: 一.移动社交 微信 ...

随机推荐

  1. Android动画总结#补间动画(Tween Animation/View Animation) #帧动画(Frame Animation/Drawable Animation)#属性动画(PropertyAnimation)

    1.共有三种动画,英文名字多种叫法如下 第一种动画:补间动画(Tween Animation/View Animation) 四个:RotateAnimation旋转. AlphaAnimation透 ...

  2. 50个实用的jQuery代码段让你成为更好的Web前端工程师

    本文会给你们展示50个jquery代码片段,这些代码能够给你的javascript项目提供帮助.其中的一些代码段是从jQuery1.4.2才开始支持的做法,另一些则是真正有用的函数或方法,他们能够帮助 ...

  3. 【技术贴】Maven打包文件增加时间后缀

    构建war包,或者jar包的,时候,maven会自动增加一个版本号和时间放在jar包后面比如poi-3.9-20131115.jar这样子,但是我自己打war包,总是给我生成一个快照的后缀report ...

  4. find+*的问题

    转自find+*的问题 不久前做移植的时候想把某个目录下的C文件都找出来,然后拷贝下,结果一直报错,我用的是*.c作为pattern.今天看论坛的时候知道为什么了. $ ls test2.c  tes ...

  5. phpStorm 配置关联php手册

    phpStorm 配置关联php手册 pasting php开发中我尝试过很多个编辑器,但用的最多的是phpStorm ,但一直因为英文太烂,很多phpStorm功能,都没用过.. 最近发现有些编辑器 ...

  6. 开发的时候,一定要及时控制CPU使用率以及使用内存大小等三个问题(一个星期检查一次)

    一直专注于功能的开发,没注意CPU和内存.昨天无意中发现两个问题: 1. 程序启动后,什么都没干,CPU就50%了(单核).现在想找原因降低使用率,感觉无从下手,要是平时就注意这个问题就好了. 2. ...

  7. Android Studio 使用笔记:Git 的配置和第一次提交到仓库

    Git客户端网址:http://git-scm.com/download/ 根据自己的使用平台下载对应的客户端.这里以Mac系统为例,当客户端软件安装配置完毕后,打开AS的配置面板,找到Git的选项 ...

  8. selectpicker下拉多选框ajax异步或者提前赋值=》默认值

    Bootstrap select多选下拉框赋值 success: function (data) { var oldnumber = new Array(); $.each(data, functio ...

  9. 《大数据Spark企业级实战 》

    基本信息 作者: Spark亚太研究院   王家林 丛书名:决胜大数据时代Spark全系列书籍 出版社:电子工业出版社 ISBN:9787121247446 上架时间:2015-1-6 出版日期:20 ...

  10. bzoj2257

    不难发现其实这个捣鼓过程就是一个辗转相减所以最小燃料是瓶容量的最小公约数然后穷举约数即可 ..] of longint; n,k,x,i,m,j,t:longint; procedure sort(l ...