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();
構造函數與初始化
在 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引擎會更方便噢、、、