七、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引擎會更方便噢、、、
相關文章
相關標籤/搜索