七、Cocos2dx 3.0游戏开发找小三之3.0版本号的代码风格

重开发人员的劳动成果,转载的时候请务必注明出处http://blog.csdn.net/haomengzhu/article/details/27691337

Cocos2d-x代码风格
前面咱们已经屡次提到 Cocos2d-x 源自于 Cocos2d-iPhone。Cocos2d-iPhone 是一个十分出色的游戏引擎,不少优秀的 iOS 平面游戏都基于 Cocos2d-iPhone 开发,而它的实现语言是 Objective-C。所以,Cocos2d-x 也就沿袭了 Objective-C 的代 码风格。 
这么作的主要缘由例如如下:
出于对 Cocos2d-iPhone 程序猿习惯的照应,以及对该引擎的尊敬; 
方便不一样语言下 Cocos2d 游戏的移植;
为了实现 Objective-C 风格的内存管理,要求引擎採用特殊的命名规范。

接下来咱们将具体介绍 Cocos2d-x 的代码风格。

命名空间与类名称
Cocos2d-x 拥有一个包括其它全部头文件的文件"cocos2d.h"。一般,咱们仅仅需要在使用时包括这个头文件,就可以使用引 擎的全部功能了。

Cocos2d-x 的类都放置于 cocos2d 命名空间下。以引擎文件夹下的"cocos/2d/CCLayer.h"为例,咱们可以看到文件的首位有两 个宏:NS_CC_Begin 和 NS_CC_END。查看宏的定义可知,这两个宏至关于把所有的类型都包括在了 cocos2d 命名空间下。
游戏中,咱们常使用引擎提供的还有一个宏 USING_NS_CC 来引用 cocos2d 命名空间:
#define USING_NS_CC using namespace cocos2d

类的命名与 Cocos2d-iPhone 一致,由类库缩写加上类名称组成,当中类库缩写採用大写,类名称採用驼峰法。
Cocos2d 2.0的 缩写是 CC,所以 Cocos2d-x 2.0的类都拥有 CC 前缀,好比表示动做的类就叫作 CCAction。
相比于Cocos2d 2.0,Cocos2d 3.0更简洁;

今后再也不见到以CC开头的类,因为CC被废掉了,并且定义的时候用auto;

举个样例:
v2.2  
CCSprite* sprite=CCSprite::create();  
v3.0  
auto sprite=Sprite::create();

若想了解不少其它信息,官方站点上有 3.X 2.X 以前的差别说明:
cocos2d-x 3.0 与cocos2d-x 差别说明连接

构造函数与初始化
在 Cocos2d-x 中建立对象的方法与 C++开发人员的习惯迥乎不一样。 在 C++中, 咱们仅仅需要调用类的构造函数就能够建立一个对象, 既可直接建立一个栈上的值对象,也可以使用 new 操做符建立一个指针,指向堆上的对象。而在 Cocos2d-x 中,不论是创 建对象的类型,仍是建立对象的方法都与 C++不一样。

Cocos2d-x 不使用传统的值类型,所有的对象都建立在堆上,而后经过指针引用。
建立 Cocos2d-x 对象一般有两种方法:
一种是首先使用 new 操做符创造一个未初始化的对象,而后调用 init 系列方法来初始化;
另一种是使用静态的工厂方法直 接建立一个对象。

如下咱们首先介绍第一种方法。

在 Objective-C 中并无构造函数,建立一个对象需要先为对象分配内存,而后调用初始化方法来初始化对象,这个过程 就等价于 C++中的构造函数。 
与 Objective-C 同样, Cocos2d-x 也採用了这个步骤。 
Cocos2d-x 类的构造函数一般没有參数, 建立对象所需的參数经过 init 开头的一系列初始化方法传递给对象。
建立对象的过程例如如下所看到的。
使用 new 操做符调用构造函数,建立一个没有初始化过的空对象。
选择合适的初始化方法,并调用它来初始化对象。
Cocos2d-x 的初始化方法都以 init 做为前缀,所以可以轻易辨认出来。初始化方法返回一个布尔值,表明是否成功初始化 该对象。

如下咱们提供一个从文件初始化精灵(CCSprite)的样例:
auto sprite1 = new CCSprite();
sprite1->initWithFile("bg.png");

在这个样例中,咱们首先调用构造函数建立一个未经初始化的 Sprite 对象,而后在 Sprite 提供的初始化方法中 选择了从文件建立精灵的初始化方法 Sprite::initWithFile(const char* filename)来初始化精灵。

另一种方法则是使用类自带的工厂方法来建立对象。
在 Cocos2d-x 中,不少类会自带一系列工厂方法,这些工厂方法是类 提供的静态函数。
仅仅要提供必要的參数,就会返回一个完毕了初始化的对象。
一般 init 系列的初始化方法都会有其相应的 工厂方法,它们的名称相似,參数一致,都可以用于建立对象。
在 Cocos2d-x 的旧版本号中,工厂方法一般以类的名称(不 包括前缀)开头,
而在 Cocos2d-x 2.0 及兴许版本号中,工厂方法的名称统一为 create。
在名称冲突的状况下,也可能採用 以 create 做为前缀的其它函数名。

咱们仍然以建立精灵为例,如下的两条语句等价;
前者为引擎旧版本号中的方法,后者为新版本号中的方法,它们都会建立一 个与第一种方法所述相似的精灵:
Sprite* sprite2 = Sprite::spriteWithFile("bg.png");
Sprite* sprite3 = Sprite::create("bg.png");

这两种方法都可以建立 Cocos2d-x 对象,然而它们在内存管理方面仍是有一点点差别的。
使用构造函数建立的对象,它的 所有权已经属于调用者了,使用工厂方法建立的对象的所有权却并不属于调用者,
所以,使用构造函数建立的对象需要调 用者负责释放,而使用工厂方法建立的对象则不需要。

在游戏中,咱们需要不断地建立新的游戏元素,一般採取的方法是从 Cocos2d-x 提供的游戏元素类派生出新的类,并在初 始化方法中创建好咱们所需的游戏元素。这个过程与微软.NET 框架下的 Windows Form 开发相似。
好比在 Hello World 中, 咱们从 Layer 类派生出 HelloWorld 类 (这是一个层) , 并重载了 HelloWorld 类的 init()方法, 在这种方法中为 HelloWorld 层加入内容。

为了保证初始化方法可以被子类重载,需要确保初始化方法声明为虚函数:
virtual bool init();
做为參考,咱们提供一个典型的 init()方法框架例如如下:
bool init()
{
 if(Layer::init())

{
//在此处写入初始化这个类所需的代码
return true;
}
return false;
}

选择器
在 Objective-C 中,选择器(Selector)是相似于 C++中的类函数指针的机制。
由于 Cocos2d-x 继承了 Cocos2d-iPhone 的 代码风格,所以也提供了一系列相似于 Objective-C 中建立选择器语法的宏,用来建立函数指针。
这些宏都仅仅有一个參数 SELECTOR,表示被指向的类方法。

在Cocos2d-x2.0中将这些宏列举例如如下:
schedule_selector(SELECTOR)
callfunc_selector(SELECTOR)
callfuncN_selector(SELECTOR)
callfuncND_selector(SELECTOR)
callfunc_selector(SELECTOR)
menu_selector(SELECTOR)
event_selector(SELECTOR)
compare_selector(SELECTOR)

从3.0開始,事件回调函数由原来的schedule_selector和menu_selector等变成CC_CALLBACK_0、CC_CALLBACK_一、CC_CALLBACK_二、CC_CALLBACK_3。

如下咱们来看第 1 章中的 Hello World 样例。
在这个样例中,咱们在 HelloWorld 类的 init()方法中加入了一个菜单,当用 户点击该菜单时,就会触发此类中的 menuCloseCallback()方法。
可以看到,初始化菜单的后两个參数各自是被调用对象与 Cocos2d-x 选择器:
 auto closeItem = MenuItemImage::create(
                                        "CloseNormal.png",
                                        "CloseSelected.png",
                                        CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));

当中CC_CALLBACK_1宏是将函数与对象绑定在一块儿,1表示这个函数有一个參数。当点击这个button时,会调用这个回调函数。node

除了基于c++11的这个形式的改变,用法与先前一样。c++


属性
C++的类成员仅仅有方法与字段,没有属性和事件,这给开发人员带来了不便。
为了实现 Objective-C 中提供的属性功能,咱们 不得不用法来模拟 get 和 set 訪问器。
Cocos2d-x 规定了属性訪问器的方法名称以 get 或 set 为前缀,后接属性名。
在 Node 中包括大量属性,
好比用于给节点作标记的 Tag 属性,它的訪问器分别为 getTag()和 setTag(int aTag),
事实上现原 理大体例如如下: 
int _tag; ///< a tag. Can be any number you assigned just to identify this node
virtual int getTag() const;
virtual void setTag(int aTag) 
    
/// tag getter
int Node::getTag() const
{
    return _tag;
}
    
/// tag setter
void Node::setTag(int var)
{
    _tag = var;
}

在这个样例中,属性的类型是 int,处理较为简单。
当涉及到内存管理,开发中咱们对数值类型、结构体类型、Cocos2d-x 对象的处理方法都不尽一样。

为每一个属性编写一个或两个訪问器方法是一项十分枯燥的任务,为了不反复性的工做,Cocos2d-x 提供了一系列宏来帮 助咱们方便地建立属性。
下表列举了所有属性相关的宏,它们定义在引擎文件夹中的"cocos\base\CCPlatformMacros.h"中。

Cocos2d-x 3.0中与属性相关的宏


这些宏仅仅要写在类的定义之中就能够。
每个宏都有 3 个參数,各自是:varType,属性类型,假设属性类型是对象,需要写成 指针的形式;
varName,属性的私有字段名称;funName,属性的訪问器名称,也就是紧接在 get 或 set 前缀后的部分。
利用 Cocos2d-x 提供的宏,以Layer为例,Layer属性定义就可以用如下一条语句取代了:
CC_SYNTHESIZE(cocos2d::Layer*, m_pLayer, Layer);

单例
相对于前面的内容,单例(singleton)则是一个很是易于理解的概念。
在 Cocos2d-x 引擎中,咱们能看到大量单例的身影, 它们大部分出现在一些系统资源管理类中。
单例模式保证了全局有且仅仅有一个实例对象,保证本身主动地初始化该对象,
使得 程序在不论何时不论什么地方都可以訪问、获取该对象。

好比,Cocos2d-x 3.0的游戏流程控制器 Director 是一个独一无二的控制器,用于切换游戏场景。
换句话说,不可能同一时候存 在两个 Director 实例。

在这样的状况下, Cocos2d-x 採用了单例的技巧。 
用户可以经过类提供的静态方法获取独一无二的实例, 而不需要本身来建立。

观察 Director 的代码:
// singleton stuff
static DisplayLinkDirector *s_SharedDirector = nullptr;
Director* Director::getInstance()
{
    if (!s_SharedDirector)
    {
        s_SharedDirector = new DisplayLinkDirector();
        s_SharedDirector->init();
    }

    return s_SharedDirector;
}

可以发现,Director 维护了一个静态的 Director 实例,在第一次使用前初始化。
为了訪问 Director 控制器,咱们 可以使用例如如下代码:
Director::getInstance()->replaceScene(newScene);
这条语句使用 Director::getInstance()获取 Director的惟一实例,而后调用 replaceScene 来切换到新场景。

郝萌主友情提示:
熟悉新风格,新特性,使用cocos2d-x引擎会更方便噢、、、
相关文章
相关标签/搜索