【转】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()函数
[cpp] view plaincopyprint?
- CCSprite* CCSprite::create()
- {
- CCSprite *pSprite = new CCSprite();//调用构造函数,产生对象
- if (pSprite && pSprite->init()) // 创建对象成功并且其init函数返回true则添加到自动释放池
- {
- pSprite->autorelease();
- return pSprite;
- }
- CC_SAFE_DELETE(pSprite); // 安全释放
- return NULL;
- }
看到了,create函数里面实质上做了两件事:1.调用构造函数 2.init()成功则添加到自动释放池。
然后看init()函数,就是自己的一些初始化工作了。
对于这个结构大家要非常熟悉,几乎可以说是一个套路。
这个二阶段构造用的很多,为了简化代码提高效率,cocos2d-x有个函数宏专门来干这个活:
[cpp] view plaincopyprint?
- #define CREATE_FUNC(__TYPE__) \
- static __TYPE__* create() \
- { \
- __TYPE__ *pRet = new __TYPE__(); \
- if (pRet && pRet->init()) \
- { \
- pRet->autorelease(); \
- return pRet; \
- } \
- else \
- { \
- delete pRet; \
- pRet = NULL; \
- return NULL; \
- } \
- }
这个跟上面CCSprite的create函数很像啊。结构几乎是一样的。
所以我们自己的类只需要用这个宏定义,然后实现init()函数就可以了。用的时候直接调用create()函数。
比如我写Ship:
[cpp] view plaincopyprint?
- #ifndef __MoonWarriorsx__Ship__
- #define __MoonWarriorsx__Ship__
- #include "cocos2d.h"
- #include "UnitSprite.h"
- USING_NS_CC;
- class Ship : public UnitSprite{
- private:
- // 速度
- int m_speed;
- // 子弹速度
- int m_bulletSpeed;
- // 生命值
- int m_HP;
- // 子弹类型
- int m_bulletTypeValue;
- // 子弹威力
- int m_bulletPowerValue;
- // 是否在投掷炸弹
- bool m_throwBombing;
- // 是否可被攻击
- bool m_canBeAttack;
- bool m_isThrowBomb;
- int m_zOder;
- // 最大子弹威力
- int m_maxBulletPowerValue;
- // 出现的初始位置
- CCPoint m_appearPosition;
- int m_hurtColorLife;
- bool m_active;
- public:
- Ship();
- ~Ship();
- // 被攻击使能
- void makeAttack(CCNode *pSender);
- // 更新
- virtual void update(float dt);
- // 射击
- void shoot(float dt);
- // 初始化
- virtual bool init();
- // 被攻击,受伤
- virtual void hurt();
- // 销毁飞船
- virtual void destroy();
- // 获取生存状态
- virtual bool isActive();
- // 碰撞矩形
- virtual CCRect collideRect();
- int getZoder();
- // 构造器
- CREATE_FUNC(Ship);
- };
- #endif /* defined(__MoonWarriorsx__Ship__) */
然后构造函数只带了一个初始化列表赋初值,没干别的事情。接着实现init()函数,所有初始化工作都在这里实现:
[cpp] view plaincopyprint?
- bool Ship::init()
- {
- // super init first
- if ( !CCSprite::init() )
- {
- return false;
- }
- // init life
- CCTexture2D * shipTextureCache = CCTextureCache::sharedTextureCache()->addImage(s_ship01);
- CCRect rec = CCRectMake(0, 0, 60, 38);
- this->initWithTexture(shipTextureCache, rec);
- this->setPosition(m_appearPosition);
- // set frame
- CCSpriteFrame *frame0 = CCSpriteFrame::createWithTexture(shipTextureCache, CCRectMake(0, 0, 60, 38));
- CCSpriteFrame *frame1 = CCSpriteFrame::createWithTexture(shipTextureCache, CCRectMake(60, 0, 60, 38));
- CCArray *animFrames = CCArray::create();
- animFrames->addObject(frame0);
- animFrames->addObject(frame1);
- // ship animate
- // 这个方法有差异
- 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);
- // revive effect
- this->m_canBeAttack = false;
- CCSprite *ghostSprite = CCSprite::createWithTexture(shipTextureCache, CCRectMake(0, 45, 60, 38));
- ccBlendFunc cbl = {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));
- return true;
- }
init函数要先调用super的init(),然后写自己的东西。
这样的二阶段构造有个好处,就是将自动释放封装起来了。因为这个create函数是个static的,创建对象成功且初始化成功就将其添加到自动释放池,然后返回对象实例。你通过create获得对象后不用管它的释放问题。
当然,你也可以标新立异,不一定就按这个来。不过关键一点是,不管你怎么构造你的实例,要确保成功并将其加到自动释放池。比如我有个子弹类不是用create创建实例的,其使用如下:
[cpp] view plaincopyprint?
- Bullet *bullet_a = new Bullet(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{
- delete bullet_a;
- bullet_a = 0;
- }
看,自己的构造函数,还要自己添加自动释放池。一看就很乱。其实这个也可以封装起来,自己实现create函数,不用那个宏定义,后续改下。
这里有一点不一样,就是CCScene的构造。
coco2d-x里面导演执行的单元是CCScene,就是场景。一个场景里面会添加很多CCLayer,即层。层里面又会添加很多元素,比如CCSprite,CCMenu等。那么场景如何构造呢?
demo里面是这一做的,在主Layer里面定义一个static的函数scene(),返回一个CCScene对象,例如:
[cpp] view plaincopyprint?
- CCScene* HelloWorld::scene()
- {
- // 'scene' is an autorelease object
- CCScene *scene = CCScene::create();
- // 'layer' is an autorelease object
- HelloWorld *layer = HelloWorld::create();
- // add layer as a child to scene
- scene->addChild(layer);
- // return the scene
- return scene;
- }
他在这个函数里面将主Layer构造出来,然后添加到场景里面。注意,所有create函数构造的对象都是一个autorelease的对象。
然后执行场景:
[cpp] view plaincopyprint?
- // create a scene. it's an autorelease object
- CCScene *pScene = HelloWorld::scene();
- // run
- pDirector->runWithScene(pScene);
看,封装好了,代码多清晰。
好了,就这么多,打完收工。
【转】cocos2d-x游戏开发(八)各类构造器的更多相关文章
- iOS cocos2d 2游戏开发实战(第3版)书评
2013是游戏爆发的一年,手游用户也是飞速暴增.虽然自己不做游戏,但也是时刻了解手机应用开发的新动向.看到CSDN的"写书评得技术图书赢下载分"活动,就申请了一本<iOS c ...
- [Android游戏开发]八款开源 Android 游戏引擎 (巨好的资源)
初学Android游戏开发的朋友,往往会显得有些无所适从,他们常常不知道该从何处入手,每当遇到自己无法解决的难题时,又往往会一边羡慕于 iPhone下有诸如Cocos2d-iphone之类的免费游戏引 ...
- (转载)如何学好iphone游戏开发
转自:http://www.cnblogs.com/zilongshanren/archive/2011/09/19/2181558.html 自从发布<如何学习iphone游戏开发>到 ...
- 【Cocos2D研究院之游戏开发】
http://www.xuanyusong.com/archives/category/ios/cocos2d_game 分类目录归档:[Cocos2D研究院之游戏开发] 201211-19 Co ...
- 《MFC游戏开发》笔记八 游戏特效的实现(二):粒子系统
本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9360993 作者:七十一雾央 新浪微博:http:// ...
- cocos2d 游戏开发实战
文章转自:http://uliweb.clkg.org/tutorial/read/40 6 cocos2d 游戏开发实战 6.1 创建cocos2d项目 6.2 cocos2d v3 & ...
- Html5 Egret游戏开发 成语大挑战(八)一般性二级页面处理
在游戏中,我们一般会有各种各样的二级页面,比如游戏暂停界面或者游戏结束界面,这些界面组成了对玩家交互主要手段,在游戏开发中,对于这些界面的coding组织是非常有学问的,如果倒退到十年前,游戏开发的老 ...
- 【python游戏编程之旅】第八篇---pygame游戏开发常用数据结构
本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 上一个博客我们一起学习了pygame中冲突检测技术:http://www.cnblogs.com/msxh/ ...
- 学习手机游戏开发的两个方向 Cocos2d-x 和 Unity 3D/2D,哪个前景更好?
如题! 首先说一说学习手机游戏(移动游戏)这件事. 眼下移动互联网行业的在以井喷状态发展.全球几十亿人都持有智能终端设备(ios android),造就了非常多移动互联网创业机会: 一.移动社交 微信 ...
随机推荐
- 偶尔转帖:AI会议的总结(by南大周志华)
偶尔转帖:AI会议的总结(by南大周志华) 说明: 纯属个人看法, 仅供参考. tier-1的列得较全, tier-2的不太全, tier-3的很不全. 同分的按字母序排列. 不很严谨地说, tier ...
- centos网络安装中的注意点
转自centos网络安装中的注意点 centos网络安装的教程网上很多,这里仅仅记录一下安装过程中网上别处提及很少的注意点. 1.centos默认会安装selinux,并且默认阻止ftp服务,所以要禁 ...
- [OJ] Find Minimum in Rotated Sorted Array II
LintCode 160. Find Minimum in Rotated Sorted Array II (Medium) LeetCode 154. Find Minimum in Rotated ...
- Yii modules中layout文件的调用
在YII中,如果我们使用了modules区分了前后台,那么在不同的modules中需要使用各自的layout文件,在使用中发现经常会调用不到modules中的layout,下面介绍一下如何才能正确的调 ...
- 在网页中插入CSS样式表的几种方法
1. 链入外部样式表 链入外部样式表是把样式表保存为一个样式表文件,然后在页面中用<link>标记链接到这个样式表文件,这个<link>标记必须放到页面的<head> ...
- cocos2d-x 添加自定义字体---中文,英文
1: 找到字体 xxx.ttf 2: 在xcode工程的 Info.plist文件中添加key Fonts provided by application, 或者 UIAppFonts(raw ...
- Interviews3D: APlatform for Interactive Handing of Massive Data Sets 读后感
横向比较: Inadequacy of current system design( 现代系统和一些软件的不足) 软件特点: Output sensitivity Out-of core data h ...
- JavaScript---网络编程(9-1)--DHTML技术演示(2-1)-表格创建的几种方式
一:用最底层的方式,该方式用来创建别的对象树也可以 代码演示: <html> <head> <title>DHTML技术演示---表格创建--用最底层的方式,其实该 ...
- HTML5 Canvas核心技术—图形、动画与游戏开发.pdf8
第6章 精灵 精灵(sprite),它是一种可以集成入动画之中的图像对象,赋予它们各种行为,精灵并非Canvas API的一部分,,但都是从它衍生而来 本章将会实现三种设计模式:策略模式(精灵与绘制器 ...
- Hadoop 配置好hive,第一次在conf能进入,第二次就不行了,怎么办?
问题描述: 在 Hadoop 配置好 hive 数据仓库,在conf目录下通过hive命令进入hive数据仓库,非常顺利. 但关闭终端,第二次按这种方式却显示,无次命令. 怎么办? 解决办法: 在h ...