十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
游戲開發(fā)的基本概念
若要進(jìn)行游戲開發(fā),首先要理解游戲的基本原理以及元素組成。在這一節(jié)中,我們將要介紹游戲的基本概念,包括游戲的流程控制,場(chǎng)景,層和精靈等。
場(chǎng)景與流程控制
游戲的主要流程
1.進(jìn)入游戲,顯示游戲主菜單
2.選擇新游戲,開始教學(xué)任務(wù)或者第一個(gè)關(guān)卡
3.選擇載入游戲,繼續(xù)以前的游戲
4.選擇設(shè)置,調(diào)整游戲的聽覺或者視覺效果
通常,我們把內(nèi)容相對(duì)不變的游戲元素集合稱做場(chǎng)景,而把場(chǎng)景之間的切換過程叫做流程控制
在Cocos2d-X中,場(chǎng)景的實(shí)現(xiàn)是CCScene.

層
層是屬于場(chǎng)景之下的游戲元素。通常,一個(gè)復(fù)雜場(chǎng)景會(huì)有很多個(gè)層,一個(gè)層會(huì)顯示一部分視覺元素,空白部分為透明或者半透明,以顯示多個(gè)層的重疊顯示。層與層之間按照順序疊加在一起,就組成了一個(gè)復(fù)雜的場(chǎng)景。也許,讀者接觸過Photoshop, 在這些編輯器中,也存在層的概念。在游戲設(shè)計(jì)中,層的概念與它們相似。
以捕魚游戲?yàn)槔?,?chǎng)景大致可以分為四層。
菜單層:懸浮于最上方的各種菜單項(xiàng)
觸摸層:處理在屏幕上的觸摸點(diǎn)擊時(shí)間
動(dòng)作層:放置魚,×××,網(wǎng)等,并處理碰撞
背景層:背景圖片
精靈
層和場(chǎng)景是其他游戲的容器,如果沒有向它們添加可見的游戲元素,他們看起來就一直是透明的。精靈則與層或場(chǎng)景不同,它隸屬于層,是場(chǎng)景中可出現(xiàn)的可見
圖形。玩家控制的主角、AI控制的NPC,以及地圖上的寶箱、石塊,甚至游戲主菜單的背景圖片都是精靈。因此,可以這樣認(rèn)為,玩家看到的一切都是精靈組成。
精靈不一定是靜態(tài)的。通常,一個(gè)精靈可以不斷變化,變化的方式包括:移動(dòng),縮放,旋轉(zhuǎn),變形,顯示消失,動(dòng)畫效果。精靈按照層次結(jié)合起來,并與玩家互動(dòng),
構(gòu)成一個(gè)完整的游戲。
節(jié)點(diǎn)和渲染樹
回顧之前的介紹,我們已經(jīng)知道了精靈、層和場(chǎng)景如何組成一個(gè)游戲的框架。精靈屬于層,層屬于場(chǎng)景,玩家和精靈互動(dòng),并導(dǎo)致游戲畫面在不同的場(chǎng)景中切換。
把每個(gè)環(huán)節(jié)拼接在一起,我們得到了完整的關(guān)系圖。
為了繪制場(chǎng)景,必須繪制層,為了繪制層,必須繪制精靈。因此,關(guān)系圖實(shí)質(zhì)上安排了圖元的繪圖方式,關(guān)系圖中的每一個(gè)元素稱為節(jié)點(diǎn),關(guān)系圖則稱為渲染樹。
渲染場(chǎng)景的過程就是遍歷渲染樹的過程。
一旦建立起渲染樹,組織復(fù)雜的場(chǎng)景就變得很簡(jiǎn)單。我們賦予每個(gè)節(jié)點(diǎn)一系列屬性,包括節(jié)點(diǎn)相對(duì)于父節(jié)點(diǎn)的位置、旋轉(zhuǎn)角度、縮放比例、變形參數(shù)等。渲染樹的優(yōu)勢(shì)在于,我們只需要考慮節(jié)點(diǎn)相對(duì)于父節(jié)點(diǎn)的屬性,就可以逐層創(chuàng)建復(fù)雜的對(duì)象或者動(dòng)作。
動(dòng)作與動(dòng)畫
動(dòng)作作用于游戲元素,可以使得游戲元素動(dòng)起來。常見的動(dòng)作有移動(dòng)、閃動(dòng)、消失等。動(dòng)作分為瞬時(shí)動(dòng)作和延時(shí)動(dòng)作,持續(xù)性動(dòng)作在一段時(shí)間內(nèi)完成,瞬時(shí)動(dòng)作在
瞬間完成。在Cocos2d-X中,動(dòng)作由CCAction類實(shí)現(xiàn),由CCAction類派生出來的持續(xù)性動(dòng)作類CCActionInterval和CCActionInstant。所有的動(dòng)作都派生自這兩個(gè)類
之一。
動(dòng)畫animation是一種持續(xù)性動(dòng)作,它只能應(yīng)用于精靈上,用于實(shí)現(xiàn)幀動(dòng)畫效果。如果電影膠片一樣,一個(gè)幀動(dòng)畫由多張靜止的圖片不斷地切換形成。靜止的圖片叫做
幀(frame),幀的序列代表一個(gè)動(dòng)畫效果。在Cocos2d-X中,我們可以使用多個(gè)幀創(chuàng)建幀動(dòng)畫序列CCAnimation,并用幀動(dòng)畫序列創(chuàng)建可以用于精靈的幀動(dòng)畫CCAnimate
Cocos2d-X的代碼風(fēng)格
命名空間與類名稱
Cocos2d-X的類都放置于Cocos2d命名空間下。以引擎目錄下的"actions/CCAction.h"為例子,我們可以看到文件的前面有兩個(gè)宏: NS_CC_Begin和NS_CC_END
類的命名與Cocos2d-iPhone一致,由類庫(kù)縮寫加上類名稱組成,其中類庫(kù)縮寫采用大寫,類名采用駝峰法。Cocos2d的縮寫是CC,所以Cocos2d-X的類都擁有CC
前綴,例如表示動(dòng)作的類就叫做CCAction
構(gòu)造函數(shù)與初始化
在Cocos2d-X中創(chuàng)建對(duì)象的方法和C++開發(fā)者的習(xí)慣迥乎不同.在C++中,我們只需要調(diào)用類的構(gòu)造函數(shù)就可以創(chuàng)建一個(gè)對(duì)象,既可以直接創(chuàng)建一個(gè)棧上的值對(duì)象,
也可以使用new操作符創(chuàng)建一個(gè)指針,指向堆上的圖像。而在Cocos2d-X中,無論是創(chuàng)建對(duì)象的類型,還是創(chuàng)建對(duì)象的方法都與C++不同.
Cocos2d-X不使用傳統(tǒng)的值類型,所有的對(duì)象都創(chuàng)建在堆上,然后通過指針引用。創(chuàng)建Cocos2d-X對(duì)象通常有兩種方法:第一種是首先使用new操作符創(chuàng)建一個(gè)未初始化
對(duì)象,然后調(diào)用init系列方法來初始化;第二種是使用靜態(tài)的工廠方法直接創(chuàng)建一個(gè)對(duì)象。
在Object-C中并沒有構(gòu)造函數(shù),創(chuàng)建一個(gè)對(duì)象首先需要為對(duì)象分配內(nèi)存,然后調(diào)用初始化方法來初始化對(duì)象,這個(gè)過程等價(jià)于C++中的構(gòu)造函數(shù).Cocos2d-X中的構(gòu)造函數(shù)
并沒有參數(shù),創(chuàng)建對(duì)象所需的參數(shù)通過init開頭的一系列初始化方法傳遞給對(duì)象。
初始化方法帶有一個(gè)bool值,表示是否成功初始化對(duì)象。比如一個(gè)從文件初始化精靈的例子
CCSprite* sprite = new CCSprite();
sprite->initWithFile("HelloWorld.png");
第二種方法則是使用類自帶的工廠方法來創(chuàng)建對(duì)象。在Cocos2d-X中,許多類會(huì)自帶一系列工廠方法,這些工廠方法是類提供的靜態(tài)函數(shù)。只要提供必要的參數(shù),就會(huì)返回
一個(gè)完成了初始化的對(duì)象。通常init方法都有對(duì)應(yīng)的工廠方法,它們參數(shù)一致,都可以用于創(chuàng)建對(duì)象。工廠的方法名稱統(tǒng)一為create,我們?nèi)匀灰詣?chuàng)建精靈為例子,
CCSprite * sprite2 = CCSprite::spriteWithFile("HelloWorld.png"); //舊版本方法
CCSprite * sprite3 = CCSprite::create("HelloWorld.png");
然而,在內(nèi)存管理方面,還是有一點(diǎn)差異。使用構(gòu)造函數(shù)創(chuàng)建的對(duì)象,所有權(quán)屬于創(chuàng)建者;而使用靜態(tài)工廠方法創(chuàng)建的對(duì)象并不屬于調(diào)用者。因此,使用構(gòu)造函數(shù)創(chuàng)建的
對(duì)象需要調(diào)用者負(fù)責(zé)釋放,而工廠方法創(chuàng)建的對(duì)象則不需要。
在游戲中,我們需要不斷地創(chuàng)建新的游戲元素,通常采用的方法是從Cocos2d-X提供的游戲元素類派生出新的類,并在初始化方法中建立好我們所需的游戲元素.
比如在HelloWorld類中,我們從CCLayer派生出HelloWorld類,并重載了HelloWorld類的init方法,在這個(gè)方法中為HelloWorld類添加內(nèi)容,為了保證初始化
方法可以被子類重載,需要確保初始化方法聲明為虛函數(shù)。
virtual bool init();
作為參數(shù),我們提供一個(gè)典型的init方法框架
bool init()
{
if(CCLayer::init())
{
//此處添加初始化這個(gè)類所需的代碼
return true;
}
return false;
}
選擇器
在Object-C中,選擇器Selector是類似于C++中的類函數(shù)指針的機(jī)制。由于Cocos2d-X繼承了Cocos2d-iPhone的代碼風(fēng)格,因此也提供了一系列類似于Object-C的
創(chuàng)建選擇器語法的宏,用來創(chuàng)建函數(shù)指針。這些宏只有一個(gè)參數(shù)SELECTOR,表示被指向的類方法。將這些宏列舉如下
schedule_selector( SELECTOR )
callfuncN_selector( SELECTOR )
callfuncND_selector( SELECTOR )
callfunc_selector( SELECTOR )
menu_selector( SELECTOR )
event_selector( SELECTOR )
compare_selector( SELECTOR )
下面我們來看HelloWorld例子,在這個(gè)例子中,我們?cè)贖elloWorld類的init方法中添加了一個(gè)菜單,當(dāng)用戶點(diǎn)擊菜單時(shí)候,就會(huì)觸發(fā)此類中的menuCloseCallback()
方法。可以看到初始化菜單的后兩個(gè)參數(shù)分別是被調(diào)用對(duì)象與Cocos2d-X選擇器
CCMenuItemImage *pCloseItem = CCMenuItemImage:: create(
"CloseNormal.png", "CloseSelected.png", this, menu_selector(HelloWorld::menuCloseCallback));
屬性
C++的類成員只有方法與字段,沒有屬性和事件,這給開發(fā)者帶來不便。Cocos2d-X 使用get和set方法來模擬。
在Cocos2d-X中,CCNode包含大量屬性,比如給節(jié)點(diǎn)做標(biāo)記的Tag屬性,它的訪問其分別是getTag()和setTag()
其實(shí)現(xiàn)原理大致如下:
int tag;
void getTag() { return tag; }
void setTag(int aTag) { tag = aTag; }
給每一個(gè)屬性編寫一個(gè)或者多個(gè)訪問器的方法是一項(xiàng)非??菰锏娜蝿?wù),為了避免重復(fù)性的工作,Cocos2d-X提供了一系列宏來幫助我們方便地創(chuàng)建
屬性,他們定義在 "platform / CCPlatformMacros.h" 中。
CC_PROPERTY 定義了一個(gè)屬性及其訪問器,沒有實(shí)現(xiàn)。通常用于簡(jiǎn)單的值類型
CC_PROPERTY_READONLY 定義了一個(gè)屬性,只包含get訪問器,沒有實(shí)現(xiàn)
CC_PROPERTY_PASS_BY_REF 定義了一個(gè)屬性,訪問器使用引用傳遞參數(shù),沒有實(shí)現(xiàn),通常用于結(jié)構(gòu)體類型
CC_PROPERTY_READONLY_PASS_BY_REF 定義了一個(gè)屬性,只包含get訪問器,且使用引用類型傳遞參數(shù),沒有實(shí)現(xiàn)
CC_SYNTHESIZE 同CC_PROPERTY, 實(shí)現(xiàn)了訪問器方法
CC_SYNTHESIZE_READONLY 同CC_PROPERTY_READONLY, 實(shí)現(xiàn)了訪問器方法
CC_SYNTHESIZE_PASS_BY_REF 同CC_PROPERTY_PASS_BY_REF,實(shí)現(xiàn)了訪問器方法
CC_SYNTHESIZE_READONLY_PASS_BY_REF 同CC_PROPERTY_READONLY_PASS_BY_REF,實(shí)現(xiàn)了訪問器方法
CC_SYNTHESIZE_RETAIN 同CC_PROPERTY, 實(shí)現(xiàn)了訪問器方法, 由于派生自CCObject類型,訪問器采取Cocos2d-X的內(nèi)存管理機(jī)制自動(dòng)維護(hù)對(duì)象的引用計(jì)數(shù)。
這些宏只要寫在類定義中就可以了。每個(gè)宏有三個(gè)參數(shù),分別是:
@ varType 屬性類型,如果屬性類型是對(duì)象,需要寫成指針的形式
@ varName 屬性的私有字段名稱
@ funName 屬性的訪問器名稱,也就是緊接在get或者set前綴后的部分
利用Cocos2d-X提供的宏,CC_SYNTHESIZE(int, tag, Tag)
就實(shí)現(xiàn)了
int tag;
int getTag( ) { return tag; }
void setTag( int aTag ) { tag = aTag; }
確實(shí)很方便
單例
單例模式保證了全局有且只有一個(gè)對(duì)象,保證自動(dòng)初始化該對(duì)象,使得程序在任何時(shí)候都可以訪問,獲取該對(duì)象。比如CCDirector:
CCDirector:: sharedDirector()->replaceScene( newScene );
這條語句利用CCDirector:: sharedDirector( ) 獲取CCDirector的唯一實(shí)例,然后調(diào)用replaceScene來切換場(chǎng)景
內(nèi)存管理
暫時(shí)跳過
工廠方法
基類中只定義創(chuàng)建對(duì)象的接口,將實(shí)際的實(shí)現(xiàn)推遲到子類。在這里,我們對(duì)它稍加推廣,泛指一切生成并返回一個(gè)對(duì)象的靜態(tài)函數(shù)。
CCObject * factoryMethod( )
{
CCObject *ret = new CCObject( );
// 在這里對(duì)ret對(duì)象進(jìn)行必要的初始化操作
ret->autorelease( );
return ret;
}
對(duì)象傳值
將一個(gè)對(duì)象賦值給某一個(gè)指針作為引用的時(shí)候,為了遵循內(nèi)存管理的原則,我們需要獲得新對(duì)象的引用權(quán),釋放舊對(duì)象的引用權(quán)。此時(shí),
release() 和 retain() 的順序就非常重要。
看下面一段代碼
void SomeClass::setObject(CCObject * other)
{
this->object->release();
other->retain();
this->object = other;
}
這里存在的隱患在于,當(dāng)other和other實(shí)際指向同一對(duì)象的時(shí)候,第一個(gè)release()可能會(huì)觸發(fā)該對(duì)象的回收,這顯然不是我們想看到的局面,
所以應(yīng)該先執(zhí)行retain()來保證other對(duì)象有效,然后再釋放舊對(duì)象。
void SomeClass::setObject(CCObject * other)
{
other->retain();
this->object->release();
this->object = other;
}
其他可行的方法也還有很多,比如使用autorelease()方法來代替release(),或者在賦值之前判斷兩個(gè)對(duì)象是否相等。在Object-C編程規(guī)范中,
推薦使用autorelease()方法代替release()方法。
release( ) 還是 autorelease( ) ?
容器
CCArray & CCDictionary Object-C 風(fēng)格
Cocos2d-X 引擎為我們提供了CCArray, CCDictionary 等Object-C風(fēng)格的容器。
使用這些容器的一個(gè)重要原因在于Cocos2d-X的內(nèi)存管理。
class CC_DLL CCAray: public CCObject
{
public:
~CCArray();
bool initWithObjects(CCObject *pObject, ...);
}
我們應(yīng)該盡量使用Cocos2d-X提供的容器類.
相關(guān)輔助宏
引用計(jì)數(shù)很奇妙也很方便,但是大部分處理過程涉及到指針,難免比較繁瑣,也容易出錯(cuò)。針對(duì)這個(gè)問題,Cocos2d-X為我們準(zhǔn)備了一系列輔助宏來簡(jiǎn)化代碼,
這些宏的頭文件包含在"CCPlatformMacro.h"中。下面列出了和內(nèi)存管理相關(guān)的宏。
CC_SAFE_DELETE(p) delete p
CC_SAFE_DELETE_ARRAY(p) delete [] p
CC_SAFE_FREE(p) free p
CC_SAFE_RELEASE(p) release( )方法釋放
CC_SAFE_RELEASE_NULL(p) release( ) + p = null
CC_SAFE_RETAIN(p) p->retain( ) 如果p為null, 則不操作
Cocos2d-X 的內(nèi)存管理原則
程序段必須成對(duì)執(zhí)行retain()和release()或者執(zhí)行autorelease()來聲明和結(jié)束對(duì)象的引用。
工廠方法返回前,應(yīng)該通過autorelease()結(jié)束該對(duì)象的引用
對(duì)象傳值時(shí)候,應(yīng)該考慮新舊對(duì)象相同的特殊情況
盡量使用release()而不是autorelease()來釋放對(duì)象引用,以確保性能最優(yōu)秀
保存CCObject子對(duì)象時(shí)候,應(yīng)該嚴(yán)格使用Cocos2d-X提供的容器,避免使用STL容器,對(duì)象必須以指針形式傳入
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。