天天看點

【HIMI轉載推薦之三】基于Cocos2dx引擎UI擴充引擎包[cocos2d-x-3c] 轉載xiaominghimi

【前言點評】

此文章Himi已經仔細看過,總體來說是篇很好的文章,是給使用-x引擎的童鞋們的福利~。真的非常感謝作者的分享,近兩年 Himi看到了越來越多的開發者們将自己的作品與勞動成果無私放在網上供給童鞋們交流與學習,真的是感覺天國越來越好了,有沒有~ 哈哈。  (比多年前才開始進行J2me開發時的Himi來說,真的現在的童鞋們好幸福!!!)

版本管理及下載下傳清單

Download

Github

Google.code

Cocos2d-x-3c 設計之路

作者:李俊霖 [email protected]

【HIMI轉載推薦之三】基于Cocos2dx引擎UI擴充引擎包[cocos2d-x-3c] 轉載xiaominghimi

此篇文章主要介紹以下幾個架構 (Cocos2d-x-3c)

CocosBase   — 場景管理及邏輯設計上的解決方案

CocosNet    – TCP長連接配接解決方案

CocosWidget – GUI系統的解決方案

Cocos2d-x

優點:高效穩定、易用(引擎本身)、開源、跨平台

缺點:缺少穩定及功能全面的工具鍊、上手難

出于對Cocos2d-x引擎的熱愛,作者也需要來稍加點評,在優點上不想多做評論,正是因為它有着諸多優點才能讓我們喜歡并使用它,以下主要來闡述一下作者個人對Cocos2d-x引擎缺點的看法與觀點。作者屬于愛較真的人,所闡述的缺點可能在各位讀者眼中不能作為缺點而存在,确實Cocos2d-x其實算是一個比較完美的跨平台引擎了。由于3.0版本的釋出,部分缺點已經得到了改善,那就先來說說3.0版本的問題。首先作者認為3.0版本定位不明确,通俗講就是目标不明确,3.0版本在釋出時明确表示出可以脫離cocos2d-iphone的老路,沿用新的技術 新的架構,不好的子產品可以直接舍去或者重構,可是在3.0版本裡卻随處可見2.0版本的老設計,CCMenu體系,CCArray(被Vector所替換),CCDictionary(被Map所替換),2.0版本的觸摸優先級等等,可否曾想過

作為一個新加入Cocos2d-x3.0陣營的開發者,在選擇上如何定義?GUI體系包含CCMenu,CocosBuilder,CocosStudio,擴充庫裡的GUI元件,(不算作者開發的CocosWidget)這些該被開發者如何選擇,如何使用呢?作者見過的已經不在少數的開發者選擇組合使用CCMenu,CocosBuilder,CocosStudio,還有擴充庫裡的CCScrollView、CCTableView等,這樣的做法是大錯特錯的,這些GUI系統從設計理論上來講是完全不能被組合的。是以作者希望的是真正的重構與設計,而不是一味的相容老版本。

跨平台環境和工程搭建基本屬于要哭的節奏,如果不是作者利用業餘的大量時間來研究Cocos2d-x,那麼作者所在公司的項目進度還處在攀岩的速度,這也是為什麼作者說它起步難的原因,雖然python模闆解決了各個平台工程的生成問題,但是對于一個即将使用Cocos2d-x來開發遊戲的公司和即将部署多平台項目的程式設計人員來講,它們需要分别了解學習ios、android、win32 (暫時不考慮其他平台)的平台項目,其中屬Android最為複雜,要部署一個Android可調試項目對于一個沒有Android相關工作經驗的人來說簡直是噩夢。當然了,在開發跨平台項目的過程中了解這些是無可厚非的,但是我們是否可以想辦法讓這個過程變得更加傻瓜化,當需要了解具體内容時,再進一步跟進深入,這樣會招來更多人的喜歡。

使設計更子產品化(在3.0上稍有展現),使引擎本身更标準化,作者覺得引擎團隊是否可以在對于引擎本身的設計上或者需求采納上更為嚴謹,這點可以向c++标準委員會及标準庫看齊這樣可以使開發者置身于非常标準環境下去工作(這句話了解起來比較抽象,可以自行了解)。

讀者拿到引擎首先就注意到的是,引擎是否能滿足需求,那就取決于遊戲本身的類型等等,那引擎到底能不能滿足需求,作者隻能這樣答複,暫時還不能完全滿足到此為止,每家公司或者每個遊戲架構制定者會有不同的做法來實作滿足自己的需求,我們可以稱為“二次封裝”,這種所謂的“二次封裝”可能分為很多不同的形式,千變萬化。有的基于Cocos2d-x的一個穩定版本開了一個單獨的分支,從此維護自己的版本,有的則加入各種各樣的邏輯架構、資源管理架構等等。作者隻能感歎民間高手多啊。那麼作者為引擎團隊提供的建議還是”标準化”的概念,那麼問題就很明顯了,目前的标準化還不夠标準,還不夠強大。

濾鏡系統在Cocos2d-x裡不适用,想讓整個場景執行去色操作?想讓整個場景執行高斯模糊?那麼抱歉,目前引擎還沒有實作,這是一個大問題,作者已經将此需求向引擎團隊送出,目前能實作濾鏡的方式之一就是繼承CCSprite,overriding the draw function,實作自己的濾鏡效果,那麼缺點也随之凸顯,一個精靈并不能執行多個濾鏡效果,并且精靈與這個效果強耦合,這并不是我們所預期的效果。

基礎回顧

在介紹Cocos2d-x-3c前,作者需要再對Cocosd2-x的基礎設計上做一個簡單明了的介紹,目的是讓讀者對Cocos2d-x本身有更深層次的思考與更廣泛的了解

主循環:

每個遊戲都有一個主循環,而Cocos2d-x的主循環位于CCDirector.cpp裡的mainLoop函數,大緻可以了解為以下結構

int main()

{

while(1)

mainLoop();

if(con)

break;

   }

return 0;

};

mainLoop裡做了這樣幾件事情,明确地按順序來說明

– 幀開始

1:計算上一幀循環到本幀循環的時間差

2:執行所有注冊了scheduler的對象和函數

3:通路目前運作的scene和所有scene樹上的節點(CCNode),我們可以稱為”渲染樹”

4:通路CCNotificationNode節點

5:顯示螢幕左下角的資訊(FPS等等)

6:交換緩沖區,把本幀所完成的所有渲染操作呈現到螢幕上

7:将CCAutoReleasePool池對象pop一次

– 幀結束

基礎機關

CCObject 用于抽象所有類型,并實作侵入式對象引用計數管理

CCNode 渲染節點(用于渲染樹)

CCSprite 元素機關(精靈)

渲染樹

渲染樹的起點為CCScene,通過getRunningScene就可以得到目前渲染樹的根節點,所有CCNode的derived class都具備可渲染(drawable)的功能。

CCNode的virtual draw函數用來覆寫後實作自定義的渲染方式。

CCNode的virtual visit函數實作了調用所有子節點的visit函數,并根據zOrder決定自己和所有子節點virtual draw函數的調用順序。

請參考CCNode.cpp源碼,注:在virtual draw或者virtual visit函數中調用addChild或者removeChild并不安全。

場景棧

渲染樹的根節點被稱之為”場景”(CCScene),同時隻能存在一個正在運作的場景,也就是RunningScene,并且RunningScene是RunningSceneStack(場景運作棧)棧頂的那個,棧頂的場景永遠是呈現在使用者界面上的那個,是以改變這個棧的結構,也就意味着将會改變呈現給使用者的場景,于是就有了場景切換的概念。棧的原則是FILO(first in last out 先進後出),CCDirector導演子產品提供了幾個接口對場景棧的管理。

pushScene與runWithScene,場景入棧

popScene 場景出棧

replaceScene 替換棧頂的場景為某個場景

popToRootScene 場景連續出棧直至棧底

popSceneStackLevel 場景連續出棧到一個等級,1代表棧底,0代表全部出棧(退出遊戲)

注:到這裡,作者有個不得不說的秘密,其實引擎并非隻提供了一顆渲染樹(CCScene渲染樹),CCNotificationNode聽說過嗎,沒錯,它就是第二顆渲染樹,但它隻是一顆正在茁壯成長的小樹苗,你可以發揮想象把它建構為一顆參天大樹(作者項目中的飄字,提示框,加載進度等等都是用它來實作的)。

侵入式的對象引用計數管理

嚴格遵循一次new或retain,一次release或autorelease,對于一個對象來講new或retain必須與release或autorelease成對出現

CCObject的derived class都具有引用計數管理的特性,當引用計數被減至0時此對象立即釋放,假設class A : public CCObject

A* a = new A();    –引用計數預設為1

a->retain();       –引用計數加1,現在為2

a->release();      –引用計數減1,現在為1

a->autorelease();  –引用計數在本幀即将結束前減1,到那時為1

a->autorelease();  –引用計數在本幀即将結束前再次減1,到那時為0,并且釋放 (再次調用autorelease)

以下列出某些常用接口會對内容增加引用計數的操作,假設this為CCNode并且class A : public CCNode

this->addChild(a); –引用計數被addChild内部所加1,現在為2(當this析構函數執行時,會把所有Children的引用計數減1)

a->release();      –引用計數減1,現在為1 (目的是把a的計數管理權完全交給this的這個Node)

也可以這樣寫

A* a = new A();       –引用計數預設為1

a->autorelease();     –引用計數在本幀即将結束前減1

this->addChild(a);    –引用計數被addChild内部加1,現在為2

this->removeChild(a); –引用計數被removeChild内部減1,現在為1,因為autorelease,本幀結束前a的引用計數将會被減至0

通常前兩句代碼會被包裝為一個static create函數,例如我們經常看到的CCLayer::create(),那麼就會有以下的寫法

A* a = A::create();

this->addChild(a);    –當this被釋放時也就意味着a的生命周期結束

其他會改變引用計數的接口(列舉其一)

CCArray::addObject    –對被添加到容器裡的元素加1 (3.0版本中該容器對應為Vector)

CCArray::removeObject –對被從容器裡移除的元素減1

CCArrry::~CCArray     –容器析構時所有元素計數減1

注:當需要釋放對象時也可以通過delete運算符來完成操作,但一定要確定已經沒有其它子產品在引用這個對象了,否則可能會出現野指針

觸摸事件

2.0版本提供的觸摸優先級這個概念對開發者有設計上的障礙,比較好的方案是3.0版本的 new event dispatch 與 CocosWidget中的事件分發模型

但為了知根知底,作者還是要列舉一下常用的形式。

所有class CCTouchDelegate的derived class都有接收觸摸事件的能力。通過addTargetDelegate(delegate, priority, true)與removeDelegate(delegate)來注冊或取消注冊事件接收。這兩個函數通常成對出現在onEnter與onExit中,切記在onExit時需要移除觸摸事件的接收,除非你有特殊需求。引擎對于觸摸事件的分發屬于”優先級隊列詢問模式”,從最優先的delegate向下依次詢問,delegate則通過ccTouchBegan的傳回值來向引擎表達自己是否關心後續事件(moved ended cancelled)傳回true表示需要關心并處理後續事件,那麼之後的觸摸事件隻會分發給這個delegate,這也就是大家所說的事件吞噬的概念。傳回false則表示并不關心後續事件,則引擎繼續向下詢問。

注:在觸摸事件的處理函數中改變渲染樹的結構(addChild,removeChild)是安全的,注冊與銷毀定時器是安全的。

定時器Scheduler

定時器可以是每幀都執行的,也可以是隔一段時間執行一次的,也可以是隻執行一次的,通常遊戲裡會有部分邏輯被放置定時器中。class CCNode自帶定時器功能,但隻有當這個Node處于Running的狀态時,定時器才會執行。全局定時器則需要用過CCDirector提供的接口來實作

注:在注冊的定時器執行函數裡改變渲染樹的結構是安全的(addChild,removeChild),銷毀或注冊其他定時器是安全的。

動作Action

class CCNode提供了一個用于運作動作的runAction接口,class CCAction的所有derived class可以被表示為一個動作。動作基本可以分為:基礎動作 basic action,容器動作 action container,調用動作 callable action。以下列舉部分動作

基礎動作:CCMoveBy CCMoveTo CCFadeTo CCFadeOut CCFadeIn CCRotateBy CCRotateTo CCJumpTo等等,這些動作用來描述改變渲染節點狀态的一個過程,如坐标,透明度,旋轉等等。

容器動作:CCSequence CCRepeat CCRepeatForever CCSpawn等等,容器動作用來包含若幹容器動作或基礎動作。

調用動作:CCCallFunc CCCallFuncO CCCallFuncN CCCallFunND等等,調用動作可以綁定一個CCObject derived class對象的函數指針。

檔案管理方面

讀取或打開檔案的方式請使用CCFileUtils::getFileData(),如果讀者你認為使用fopen或者stl裡的fstream那你就大錯特錯了,作者所在公司的項目上因為這個吃了點虧。

注:CCFileUtils::getFileData()傳回的const char* data必須手動釋放,例如delete[] data,如果讀者有興趣,可以到Cocos2d-x2.2左右版本的庫代碼裡去搜尋這個函數,你會驚訝的發現有很多地方都遺漏了delete[],進而導緻記憶體洩露,至少作者在Cocostudio的庫裡搜出來好幾處。是以目前的解決方案隻有用腦袋記着要釋放掉。

GUI系統

正如作者所述,在選擇GUI系統時,千萬不要選擇組合多種GUI體系來開發,如果讀者您不打算考慮CocosWidget的話,作者建議您選擇CocoStudio。CCMenu體系基本就是一個神來之筆,感覺它的出現更像是一個為了滿足部分需求的臨時性解決方案,作者強烈建議您抛棄CCMenu,因為它根本不在考慮範圍内CocosBuilder體系是早期Cocos2d-iphone上的一個擴充庫,CocosBuilder原作者早已放棄繼續維護CocosBuilder,但是目前依然有很多開發者更傾向于使用CocosBuilder從結構上來分析,CocosBuilder的事件分發模型完全是照搬引擎本身那套帶有優先級的概念模型,控件與控件之間基本沒有任何關系,完全通過優先級來管制。但事實并非如它所願,控件與控件,或者控件與容器元件之間必定是要有連帶關系的,很顯然CocosBuilder裡提供的元件是做不到這點的。如果這點都做不到,那就沒法再接着讨論事件是如何分發、如何管理的。但是CocosBuilder是目前唯一在mac os x 上支援的Cocos2d-x的GUI編輯器,那這下就可以了解選擇它的理由了。作為發開者的您,選擇CocosBuilder是基本沒有問題的,但是作者更推薦您選擇CocosWidget或者CocoStudio。CocoStuido已經從貧民階段提升為屌絲階段,也相信在不久的将來會發展到高富帥階段,如果在您不考慮還沒有編輯器支援的CocosWidget,那麼作者一定會推薦您選擇CocoStudio。CocosWidget将會在下文介紹

網絡庫

引擎提供curl與CCHttpClient來實作Http協定的網絡互動,長連接配接的一般解決方案是ODSocket或BSDSocket,不過作者強烈推薦您使用CocosNet提供的長連接配接解決方案,CocosNet将會在下文介紹

線程

Cocos2d-x可以幫助你實作跨平台多線程,頭檔案統一引入<pthread>,在win32下有一份模拟實作pthread的代碼。請參考引擎源碼。

Cocos2d-x-3c CocosBase

那麼接下來作者先介紹第一個架構 Cocos2d-x-3c CocosBase

CocosBase提供消息廣播機制,資源異步預加載,模态對話框,場景緩存,雙場景渲染樹,還有比引擎更進階的場景管理方案。

1.雙場景渲染樹以及模态對話框

作者需要來詳細的解釋什麼是雙場景渲染樹,以及為什麼需要這樣的結構。我們對引擎渲染樹的概念來自class CCScene,它是作為引擎唯一渲染樹的根

(如果不加以封裝或是說不考慮CCNotificationNode的情況下),那麼我們所編寫或實作的所有帶有描述渲染對象的結構或子產品都隻能是存在于CCScene樹上的。(引擎也隻允許這麼做,除非你改變引擎的實作)例如遊戲界面,場景,對話框,購買框,提示等等這些很複雜而又多變的元素,但有時候這并不是我們所想要的結果,讓我來舉個常見的例子,首先我們實作了一個RPG遊戲的主場景(帶有描述玩家本身或其他玩家等等複雜事物的場景),接下來需要加入一個背包功能,但對于背包界面的需求是,并不覆寫整個螢幕,并且在打開時,還能看見背包界面下層的遊戲主場景。您可能想到的第一種方式就是,背包界面作為一個Layer,使用addChild接口加入到主場景上。此種方案雖然直覺通用,但從設計上來講簡直是糟糕,請允許作者來分析一下此種方式的缺點,當使用addChild把背包界面直接加入到主場景上時,背包界面便于主場景産生了一個上下級節點的關系,上級節點有責任來維護下級節點的狀态等(例如關閉打開背包界面或改變相應狀态),當這種二級界面數量逐漸增加時,主場景上便産生了大量雷同的代碼,用來維護不同的二級界面,而且還隻是假設這種關系隻有一層。當這種關系發生在多場景并且發生多級界面的情況下,那麼這種管理方案就顯的太吃力了。更别說ZOrder與觸摸優先級的控制,因為那簡直就是一場噩夢。

現在換個思路,我們可以把場景抽象為兩種類型,分别是基礎場景與UI場景,CocosBase為它們提供了一個共同的抽象類,class CCSceneExtension

基礎場景與引擎的CCScene概念基本相同,通過一個RunningSceneStack(場景運作棧)來管理,CCSceneManager提供了幾個與CCDirector功能相似的接口來管理基礎場景的切換。

pushScene(scene, extra),runWithScene(scene extra) 場景入棧

replaceScene(scene, extra) 替換棧頂場景

popScene(extra) 使棧頂場景出棧

popToRootScene(extra) 連續出棧直至棧底

popSceneStackLevel(level, extra) 連續出棧至一個等級,0為退出遊戲,1為棧底。

UI場景則是在基礎場景之上的一個場景清單(并不是以棧來管理),CCSceneManager也同樣提供接口來管理UI場景

runUIScene(scene, extra) 打開一個UI場景

popUIScene(scene) 關閉一個UI場景

注:以上的extra可以是CCObject的任何一個derived class對象,這個參數是場景切換時所附加的參數,可以被下一個出現的場景所擷取。CocosBase提供了一個捆綁資料的類名為CCBundle,它通常是用來作為場景切換時需要傳遞的參數。

那麼再回到上例所說明的情況下,我們可以把遊戲的主場景作為一個基礎場景,背包界面則可以作為一個UI場景,隻通過兩個接口則可以控制背包界面的打開與關閉,并且做到了結構上的解偶。那麼讀者您可能還比較關心的是ZOrder與Touch Priority。不用擔心,CCSceneManager内部會根據打開UI場景的順序來控制顯示(同時打開多個UI場景的情況下)。我們需要重點讨論的是Touch Priority以及如何實作一個模态場景或者說是模态對話框(看你自己的了解方式)。當背包界面被打開時,我們通常希望由它來處理觸摸事件,并不希望這些事件被傳遞到到主場景或者是下層場景(可能背包界面之下還有其他UI場景),那麼CCSceneManager提供這樣的解決方案,使用名為getTouchPriority的函數來獲得一個值,這個值代表觸摸優先級,它是由内部為你計算的一個優先權最高的動态優先級,計算方式很簡單,每次調用getTouchPriority函數時,傳回的值都比上次小1(值越小越優先,别忘了這一點),有了這個法寶,那我們可以在一個時機内把此場景和場景内具有優先級特征的元素(例如CCMenu,作者已經在上文提出将它抛棄,在這裡隻是用它來做個示範)的優先級置為這個值,關于這個時機,我們可以選擇場景的onSceneEnter回調函數(具體在下文詳細介紹),這個函數您可先暫時了解為當場景出現或再次出現時被調用。通過以上若幹步驟,就可以保證呈現在最上面的場景是最優先接觸摸收事件的。那麼剩最後一個問題就是模态與非模态,很簡單,使本場景的ccTouchBegan函數永遠傳回true則可以實作模态,反之則繼續向下傳遞。

如果讀者您覺得以上描述非常複雜難以被了解,那麼來換一種思路吧,這下作者來介紹另一種非常簡單直白的優先級與模态處理方式,那就是與CocosWidget結合使用,修改CCBaseMacros.h的USING_COCOSWIDGET宏定義為1并包含cocos-widget.h頭檔案,使CCSceneExtension繼承于CWidgetWindow,通過調用setModalable(bool)函數來設定此場景是否為模态。那麼觸摸優先級呢?讀者您可以完全抛棄這個概念了。

注:如果讀者您決定使用與CocosWidget結合的方式來管理,那麼請您一定要抛棄CCMenu或者CCTableView這樣不健全的元件,并且也不能與CocoStuido和CocosBuilder結合使用。全部使用CocosWidget内部提供的元件,并且最好以CLayout代替CCLayer。具體關于CocosWidget下文将詳細講解。

2.場景對象從哪來

場景對象從哪來?這是一個值得探讨的問題,也是考驗您對于場景設計概念上最基礎的問題之一。CCSceneManager提供了專門為您管理場景執行個體的功能。對于class CCSceneExtension的說明是,您最好不要讓自己以任何形式執行個體化它,例如create、new等(因為這完全是由内部來做的事情)。開發者需要做的事情隻是定義一個系統資料庫,用來告知CCSceneManager目前你的遊戲中包含了哪些場景,CocosBase提供了一個全局宏,名為REGISTER_SCENE_CLASS(scene),使用它來注冊一個場景,其中參數scene為場景的類名。一般我們将這樣的注冊代碼統一寫在AppDelegate.cpp的初始化函數中(具體請參考示例代碼),CCSceneManager提供兩個函數,或使用兩個宏來擷取或執行個體化一個場景對象,這兩個宏分别為LoadScene(scene class name) 通過場景類名字元串來執行個體化這個場景,但是否真的執行個體化取決于這個場景是否已經存在于場景緩存池中,若存在則直接傳回。SeekScene(scene class name) 通過場景類名字元串來搜尋這個場景,如果這個場景出現在場景緩存池、或者RunningSceneStack或UIScenesPool中。如果搜尋未果,傳回NULL。不知讀者您是否已經了解上文的含義。通過這兩個宏,我們則可以在程式執行時的任何角落(注冊之後)裡,通過類名字元串就可以達到執行個體化或搜尋場景的功能了。這種方法不僅友善,并且解決了場景與場景實作的源檔案之間複雜的頭檔案包含關系,這些頭檔案應該統一被appDelegate.cpp所包含(用來實作注冊)。

注:LoadScene會根據場景是否設定過緩存屬性來決定,執行個體化後是否把它加入場景緩存池。

3.場景生命周期以及資源預加載

介紹class CCSceneExtension的幾個virtual callback function。

onLoadResources  當場景初次被執行個體化時會調用,用于提前加載各種資源

onLoadResourcesCompleted  當資源加載完成後調用(在這裡可以做的事情比如說,關閉正在加載的等待框等)

onLoadScene  當加載場景時調用,用于初始化所有元素

onEnterScene  當場景出現時調用

onExitScene  當場景離開時調用

在onLoadResources裡可以做加載資源相關的事情,class CCSceneExtension提供了兩個函數來描述加載一個圖像資源,

addImage(file)  同步方式加載

addImageAsync(file)  異步方式加載

當某個場景正在切換但有異步加載的行為時,CCSceneManager會等待這個場景,直到資源全部加載完成後,才開始執行切換操作。

注:在同一幀之内使用兩次或以上replaceScene與popScene有可能會出現未定義行為,是以盡可能保證在同一幀内,有且隻有一次切換操作。

4.場景緩存

class CCSceneExtension提供setCachable(bool)函數來讓您在場景初始化時描述此場景是否緩存。CCSceneManager提供下列接口來管理緩存場景

removeCachedScene(scene class name) 把指定的場景從緩存池中移除

removeAllCachedScenes()  移除緩存池中的所有場景

removeUnusedCachedScenes() 移除所有在緩存池中但是并沒有運作的場景

5.消息廣播

如果您說看到這個名詞會想起Windows消息循環,那這裡也有幾分相似之處。CocosBase裡所謂的消息廣播概念,即是由CCMsgManager提供的PostMessage函數來發出廣播消息,所有class CCMsgDelegate的derived class都具備接收廣播消息的權利,通過overriding the virtual onMessage回調函數來實作。class CCSceneExtension是多繼承于class CCMsgDelegate的,是以場景對象都是具備有接收廣播消息的功能,但條件是這個場景處于Running狀态(具體請參考源碼)。但有時我們并不想讓消息散播出去,而是讓指定的消息代理來接收這個消息,那麼使用PostMessage的重載函數,指定第一個參數為目标消息代理即可實作。

PostMessage(int, CCObject, wParam, lParam) 将消息廣播出去

PostMessage(delegate, int, CCObject, wParam, lParam) 将消息發到指定消息代理

讀者還需要額外的了解兩個函數,這兩個函數用來注冊或取消注冊消息代理。CCMsgManager提供:

registerMsgDelegate(delegate)  注冊消息代理

unregisterMsgDelegate(delegate)  取消注冊消息代理

注:作者希望與SeekScene宏結合來實作把消息發到指定場景身上。

6.場景切換特效

基礎場景的切換(push, replace)操作可以通過切換特效來實作,CCSceneExTransition.h中定義了所有場景切換的方式(與引擎本身提供的完全一緻),具體使用方式請參考示例源碼。讓您遺憾的是,作者未能提供UI場景的切換特效。

Cocos2d-x-3c CocosNet

在長連接配接遊戲的開發中,CocosNet有着出色的性能,良好的設計,以及易用性。

1.良好的設計及易用性

CocosNet内部采用select無阻塞通信模型,其帶來的好處就是不用開啟另一個線程來專門維護Socket,所有讀寫操作全部在主線程内進行,更準确的說就是在mainLoop内的某個Scheduler對象處理函數内進行。一個CCNetDelegate對象用來描述一個連接配接,其内部維護了一個發送隊列以及一個接收緩沖區,在每幀内會把發送隊列裡的資料按順序發出去,并且讀取所有已經在緩沖區的資料。那麼讀者擔心的可能是在接收大資料及發送大資料的時候,會不會由于持續時間長而導緻卡幀。CocosNet提供了兩種資料發送及接收的方式,一種是所有收發操作全部在一幀内完成(大資料會導緻卡幀),另一種是收發操作在每幀内隻進行一次,具體内容參見HANDLE_ON_SINGLE_FRAME宏定義。

2.出色的性能

CocosNet内提供C數組實作的超高效緩沖容器CCBuffer,并幾乎包含所有内置資料類型的流操作,具體請參考CCBuffer.h内聲明的函數,

3.易用性

開發者使用CocosNet時,需要繼承自CCNetDelegate來管理一個獨立的連接配接,連接配接狀态的生命周期則由幾個virtual function來管理。

onMessageReceived(buffer)  當讀到消息時發生調用

onConnected()  當連接配接成功時發生調用

onConnectTimeout()  當連接配接逾時發生調用

onDisconnected()  當連接配接中斷時發生調用

onExceptionCaught(status)  當連接配接出現某種異常時調用

USING_PACKAGE_HEAD_LENGTH宏用來描述整個收發過程,是否使用標頭長度的方式,作者解釋一下這個基礎知識,標頭長度的解釋是在整個發送或接收的資料標頭部,有一個4個位元組的int型數字(是否是4位元組由作業系統決定),這個數字代表整個資料包的包長(不包括這個表示長度的數字)。如果USING_PACKAGE_HEAD_LENGTH被定義為1,則在發送資料包時,由内部自動為發送的資料標頭部加上一個長度數字,而讀取資料包時,則會先讀取長度,再根據長度讀取整個包的内容,具體請參考CCNetDelegate.cpp源碼。

Cocos2d-x-3c CocosWidget

CocosWidget是基于Cocos2d-x移動跨平台遊戲引擎的一套免費開源、功能強大、高效率、簡封裝的GUI庫。

CocosWidget目前的控件數量已經達到了26個,遠遠超過其它GUI解決方案

Widget               基礎控件

WidgetWindow         控件樹根

Button               按鈕控件

CheckBox             選擇框控件

ControlView          遊戲操作杆

GridView             網格容器控件 豎向

GridPageView         網格頁容器控件 橫豎向

ImageView            紋理容器控件(精靈)

ImageViewScale9      九宮格紋理容器控件

Label                文字控件

LabelAtlas           文字圖塊控件

LabelBMFont          圖像文字集控件

ListView             連結清單滑動容器控件

PageView             頁面滑動容器控件

Layout               基礎容器控件

PanelColor           顔色容器控件

ProgressBar          進度條控件

ScrollView           基礎滑動容器控件

Slider               滑塊控件

TableView            表格制滑動容器控件

ToggleView           開關控件

ColorView            顔色控件

GradientView         漸變控件

ExpandableListView   可伸展連結清單滑動容器控件

TextRich             富文本控件

TextArea             文本區控件

在3c版本中,CocosWidget提供了大家矚目以待的富文本控件、可伸展滑動容器控件等。本次更新,CocosWidget改進了整體結構及性能,CPanel重命名為CLayout,CWidgetLayout重命名為CWidgetWindow。

1:CocosWidget是目前唯一完全支援Lua Binding與富文本的GUI庫。

2:擁有完整的Cpp與Lua示例代碼,Cpp與Lua示例效果相似度99%,代碼簡潔減少學習成本。

3:在控件數量上絕對不會輸于任何一款GUI架構。

4:完美的控件事件分發模型,拓展性強。

5:支援多點觸摸,同時多個控件響應觸摸操作。

6:所有控件都是從CCNode繼承而來,與引擎完美結合。

7:支援長點選事件,輕而易舉實作拖拽功能。

【HIMI轉載推薦之三】基于Cocos2dx引擎UI擴充引擎包[cocos2d-x-3c] 轉載xiaominghimi
【HIMI轉載推薦之三】基于Cocos2dx引擎UI擴充引擎包[cocos2d-x-3c] 轉載xiaominghimi
【HIMI轉載推薦之三】基于Cocos2dx引擎UI擴充引擎包[cocos2d-x-3c] 轉載xiaominghimi
【HIMI轉載推薦之三】基于Cocos2dx引擎UI擴充引擎包[cocos2d-x-3c] 轉載xiaominghimi
【HIMI轉載推薦之三】基于Cocos2dx引擎UI擴充引擎包[cocos2d-x-3c] 轉載xiaominghimi
【HIMI轉載推薦之三】基于Cocos2dx引擎UI擴充引擎包[cocos2d-x-3c] 轉載xiaominghimi
【HIMI轉載推薦之三】基于Cocos2dx引擎UI擴充引擎包[cocos2d-x-3c] 轉載xiaominghimi
【HIMI轉載推薦之三】基于Cocos2dx引擎UI擴充引擎包[cocos2d-x-3c] 轉載xiaominghimi
【HIMI轉載推薦之三】基于Cocos2dx引擎UI擴充引擎包[cocos2d-x-3c] 轉載xiaominghimi
【HIMI轉載推薦之三】基于Cocos2dx引擎UI擴充引擎包[cocos2d-x-3c] 轉載xiaominghimi
【HIMI轉載推薦之三】基于Cocos2dx引擎UI擴充引擎包[cocos2d-x-3c] 轉載xiaominghimi

本文轉自 xiaominghimi 51CTO部落格,原文連結:http://blog.51cto.com/xiaominghimi/1410732,如需轉載請自行聯系原作者

繼續閱讀