說(shuō)在前面的話:棋牌游戲市場(chǎng),大部分都是品質(zhì)低劣,生命周期短暫,絕大部分原因是因?yàn)槠迮朴螒蜷_(kāi)發(fā)成本低,對(duì)開(kāi)發(fā)人員的要求也低。大部分團(tuán)隊(duì)只需要快速出成品,只要有東西快速賺錢就可以了。16年的私人房模式,再次引爆了棋牌市場(chǎng)。我也該兌現(xiàn)我的承諾,跟大家分享下怎么架構(gòu)和實(shí)現(xiàn)這套框架來(lái)滿足棋牌游戲需求的。 經(jīng)過(guò)幾個(gè)月的努力,終于說(shuō)服老板,以及各種上級(jí),實(shí)施這套解決方案。現(xiàn)在框架OK了,也利用這套框架架構(gòu)開(kāi)發(fā)了多款游戲,雖然過(guò)程很艱辛,但是還是很值得。秉承保密原則,本人并不會(huì)將框架代碼放出,只做技術(shù)交流。 根據(jù)之前在日立及IBM的項(xiàng)目經(jīng)驗(yàn),大部分成熟產(chǎn)品都會(huì)有一套完整的解決方案。不斷的積累,終大道至簡(jiǎn)。這也是這個(gè)框架命名Theway的來(lái)源,希望coding的路上越走越輕松!
一、原型 符合棋牌項(xiàng)目框架,快速換皮,快速融合。多渠道多包體。自由拆裝。 一次開(kāi)發(fā)核心玩法,快速自由迭代各種市場(chǎng)版本。
二、架構(gòu)設(shè)定 * 解耦,復(fù)用性,拓展性 * 多自由度、可分拆多項(xiàng)目開(kāi)發(fā),符合敏捷需求 * 品質(zhì)保證體系 * 高效開(kāi)發(fā) * 支撐公司大部分業(yè)務(wù)
三、模塊設(shè)計(jì)概要 減少客戶端對(duì)Cocos2d-x引擎的依賴程度和降低耦合度,將引擎必要的初始化、邏輯更新、渲染、資源管理等交給底層處理,是客戶端邏輯開(kāi)發(fā)不需要過(guò)于依賴引擎層,同時(shí),為了避免客戶端代碼中頻繁、直接的調(diào)用平臺(tái)相關(guān)諸多功能,我們將平臺(tái)相關(guān)的功能封裝在引擎封裝模塊內(nèi)。這部分我們可以叫做BaseCore部分。 
1、引擎封裝模塊 (EngineSystem) * Cocos2d-xAPI的封裝整合,綁定到Lua。關(guān)掉3D模塊,另外不再使用擴(kuò)展庫(kù)。 * 達(dá)到可以隨意切換Cocos版本,現(xiàn)階段選擇比較穩(wěn)定的版本 * 自定義控件等綁定到Lua * 跨平臺(tái)特性處理 * 支付相關(guān)模塊特殊處理 * 腳本加密解密處理 * 必要的時(shí)候,可以將腳本層換成js綁定,然后將邏輯代碼修改成Lua的,就可以支持H5了
2、 UI系統(tǒng)(GUISystem) * UI的一些基類,例如彈出框可以將如下屬性封裝成一個(gè)Dialog對(duì)象,派新類自然擁有這些屬性了。可設(shè)置大小并且?guī)в嘘P(guān)閉按鈕的一個(gè)基本視圖,另外子類不再需要去設(shè)置dismiss了。 * 還有類似于Toast的創(chuàng)建,以及一些基本控件完全可以架構(gòu)一個(gè)工廠對(duì)象,從而省略很多的基本控件的構(gòu)造代碼。當(dāng)然也可以在Lua中通過(guò)配置文件來(lái)配置基本UI。 * 健全的紋理管理規(guī)則及清理規(guī)則,紋理緩存在場(chǎng)景切換后不會(huì)移除。可以考慮逐幀加載,將紋理分級(jí),公共資源可以不remove,先刪除可能不再使用的幀動(dòng)畫(huà)資源等。 * 特別設(shè)計(jì)有限狀態(tài)機(jī)管理紋理內(nèi)存,動(dòng)態(tài)控制空間。以及利用狀態(tài)機(jī)的事件特性來(lái)控制動(dòng)態(tài)跳轉(zhuǎn)。
3、 網(wǎng)絡(luò)模塊(NetSystem) * Socket采用TCP/ip協(xié)議,封裝伯克利套接字接口,設(shè)計(jì)接受和發(fā)送隊(duì)列,通過(guò)互斥信號(hào)鎖來(lái)處理隊(duì)列共享問(wèn)題。因?yàn)閖oin函數(shù)調(diào)用的地方會(huì)阻塞主線程,我們可以考慮用detach方式,完全是交給系統(tǒng)處理,另外可以考慮第三個(gè)線程來(lái)開(kāi)辟世界聊天或活動(dòng)的這種比較頻繁的協(xié)議(視情況),并且將協(xié)議解析及Lua的table序列化放在C++層。暴露基本接口給Lua腳本層,在腳本層處理網(wǎng)絡(luò)心跳、斷網(wǎng)重連相關(guān)的邏輯。順便我們要支持IPv6的處理,這里只需要將地址解析、Socket初始化函數(shù)做兼容。接受子線程跟UI線程同步使用Cocos2d-x提供的事件來(lái)處理,然后C++將這個(gè)數(shù)據(jù)POP到Lua層,Lua這邊根據(jù)協(xié)議頭回調(diào)函數(shù),或者是通過(guò)事件的方式派發(fā)到具體的業(yè)務(wù)。 * 對(duì)于一些通用的協(xié)議,Lua層設(shè)計(jì)成搶占方式,或者是添加一個(gè)tag來(lái)標(biāo)記目前這條協(xié)議是處于模塊。 * 設(shè)計(jì)模式上考慮使用生產(chǎn)-消費(fèi)模式,盡量讓協(xié)議的讀寫(xiě)跟業(yè)務(wù)內(nèi)容解耦。協(xié)議層的封拆包全部用python腳本生成的lua文件自動(dòng)化處理,發(fā)送跟接受都是接受一個(gè)table,省去客戶端的部分工作。 * Http,我們可以封裝,上傳下載,以及我們?nèi)罩旧蟼飨嚓P(guān)的模塊等。如果使用3.11以下版本,需要替換libcurl,針對(duì)蘋(píng)果IPv6問(wèn)題。 * 結(jié)合日志模塊,將協(xié)議交互寫(xiě)在一個(gè)文件方便查看 架構(gòu)圖如下:
4、數(shù)據(jù)管理模塊(DBSystem) 類似于ORM的設(shè)計(jì)架構(gòu),調(diào)用者不需要關(guān)注實(shí)現(xiàn)細(xì)節(jié),來(lái)處理一些數(shù)據(jù) 音效相關(guān),如音量關(guān)閉,音量大小等類似數(shù)據(jù)的處理 一些可以緩存在本地的數(shù)據(jù),如一些公告之類的文本信息
5、更新模塊(UpdateSystem) * 資源熱更新,用于部分Bug修改等。 * 模塊下載,大廳可以選擇部分模塊進(jìn)行熱更,下載完后,即可重新啟動(dòng)虛擬機(jī),或reset Package。達(dá)到真正熱更意義。
資源熱更新: 通常我們會(huì)在游戲中會(huì)出現(xiàn)一些小Bug或者需要更換部分圖片素材,或者部分配置文件。來(lái)適應(yīng)運(yùn)營(yíng)策略的部分小版本更新。
模塊化更新: 大廳合集中,下載相應(yīng)的模塊,然后再點(diǎn)擊就可以玩相應(yīng)的模塊了。技術(shù)設(shè)計(jì)上,可以將資源熱更下來(lái),即刻reset Lua的Package。或者將下載的模塊添加到搜索路徑。
版本管理: 1、trunk維護(hù)一個(gè)BaseCore版本,有改動(dòng),其它所有包體都要考慮更新版本。作為一個(gè)大版本處理。后期項(xiàng)目多了,有改動(dòng)可必須拉分支進(jìn)行修改,然后同步到trunk。 2、業(yè)務(wù)模塊在BaseCore沒(méi)有改動(dòng)的情況下,完全可以不用更新程序包,直接熱更新即可。作為一個(gè)小版本。小版本可以在一個(gè)新迭代后拉一個(gè)腳本Tag版本。 3、SVN管理。需要嚴(yán)格控制版本的關(guān)系。并且做好記錄。
6、音頻模塊(SoundSystem) * 統(tǒng)一音頻解決方案,整個(gè)游戲中只有一套API * 可以區(qū)分平臺(tái)自動(dòng)匹配資源名稱,如android自動(dòng)將后綴改成.ogg。iOS改成mp3等 * 提供音頻文件預(yù)加載
架構(gòu)圖: 
7、日志系統(tǒng)( LoggerSystem) * 分級(jí)別的日志處理,類似log4j分Tag處理,更好的區(qū)分日志文件。 * 分文件處理,如果網(wǎng)絡(luò)協(xié)議日志,行為日志等。 * 配合自動(dòng)化測(cè)試,添加相應(yīng)的行為日志為Bug修改提供幫助。 * 客戶端可以設(shè)計(jì)將日志文件上傳到日志后臺(tái)。根據(jù)用戶ID命名。 架構(gòu)圖: 
8、事件系統(tǒng)( EventSystem) 考慮到框架總體的拓展性,我們完全使用事件驅(qū)動(dòng)模型(Event-driven)來(lái)設(shè)計(jì)和開(kāi)發(fā),將客戶端中事件的觸發(fā)時(shí)機(jī)和具體處理邏輯徹底分隔開(kāi)。游戲的各個(gè)模塊,僅需要注冊(cè)、監(jiān)聽(tīng)和實(shí)現(xiàn)其關(guān)心的消息事件,而無(wú)須關(guān)心事件何時(shí)被觸發(fā),降低了總體耦合度。游戲中所有UI面板的隱藏/顯示、事件響應(yīng)、音效的播放/停止、游戲流程的切換、游戲角色狀態(tài)遷移等,完全通過(guò)事件驅(qū)動(dòng)方式開(kāi)發(fā);同時(shí)這種基于事件的處理方式,為項(xiàng)目使用動(dòng)態(tài)腳本拓展提供了支持:腳本層省去對(duì)邏輯代碼的大量直接調(diào)用,通過(guò)消息事件完成腳本層和邏輯層的交互調(diào)度,大大簡(jiǎn)化了開(kāi)發(fā)的復(fù)雜度。 * 解決多線程消息通知,類似于notification方式。 * 處理模塊間耦合,配合狀態(tài)機(jī),來(lái)處理UI或者說(shuō)是模塊的行為。 * 處理全局系統(tǒng)數(shù)據(jù)等。如玩家數(shù)據(jù)
9、配置系統(tǒng)( VariableSystem) * 開(kāi)發(fā)及運(yùn)營(yíng)包體配置 * 游戲中一些配置,支持差異化包設(shè)置 * 這些配置包括部分的動(dòng)態(tài)配置,如大廳的布局位置等
10、自動(dòng)化測(cè)試系統(tǒng)( AutoTesterSystem) * 提供簡(jiǎn)單的測(cè)試腳本支持。如重復(fù)進(jìn)行某一個(gè)操作,所以每一個(gè)核心業(yè)務(wù)都需要預(yù)留測(cè)試接口,然后結(jié)合我們的行為日志,充分利用休息的時(shí)間,讓其自動(dòng)測(cè)試。 * Oriented日志。主要用來(lái)追蹤用戶操作行為,方便測(cè)試路徑重現(xiàn),只用在測(cè)試階段。 * 腳本Crash后臺(tái),腳本測(cè)試比較難以Debug,將xpcall捕捉到的日志提交后臺(tái),目前情況是有一個(gè)簡(jiǎn)單的javaWeb日志追蹤頁(yè)面。所以只是作為內(nèi)測(cè)用。 * 自動(dòng)化測(cè)試的時(shí)候,可以借助xcode等工具來(lái)查看內(nèi)存情況。
四、性能優(yōu)化 1、紋理資源的優(yōu)化、場(chǎng)景資源的優(yōu)化 開(kāi)發(fā)過(guò)程中,從嚴(yán)控制紋理,按照相應(yīng)的Block合并大圖,適當(dāng)情況下,可以降低清晰度。另外場(chǎng)景管理包含資源的管理,例如某個(gè)動(dòng)畫(huà)在特定的場(chǎng)景中出現(xiàn),我們可以直接將著部分資源在緩存中移除。 公共資源可以常駐在緩存中 如果對(duì)包體要求更嚴(yán)格,可以適當(dāng)考慮將圖片壓縮成pvr格式(一種顯卡可以直接識(shí)別的格式,目前市面上的刀塔傳奇采用的這種方案),但是這種情況是沒(méi)有alpha通道的,也就是說(shuō)透明度設(shè)置有問(wèn)題,只能是作為一種備用方案。 2、將一些耗時(shí)的操作放在C++層,如讀取配置文件,異步加載音頻文件等等。 3、網(wǎng)絡(luò)層采用多線程方式,以降低對(duì)主線程的影響。
五、質(zhì)量及規(guī)格標(biāo)準(zhǔn)化 1、客戶端架構(gòu)標(biāo)準(zhǔn) 方案切實(shí)可行,并且性能是第一位的,或者說(shuō)是開(kāi)發(fā)效率上一個(gè)臺(tái)階。 2、代碼開(kāi)發(fā)標(biāo)準(zhǔn) 分兩部分,第一部分是底層代碼,健壯、高效,并且是討論過(guò)、并切實(shí)可行。第二部分腳本代碼需要從代碼風(fēng)格上進(jìn)行管理上的強(qiáng)制要求。 3、代碼Review標(biāo)準(zhǔn) 按照約定好的代碼開(kāi)發(fā)標(biāo)準(zhǔn),切實(shí)實(shí)行,原則上實(shí)行捉對(duì)協(xié)作開(kāi)發(fā)。
六、課題方案管理 適用范圍: 1、架構(gòu)及性能上的優(yōu)化。 2、偏平臺(tái)化的技術(shù)研究。 3、對(duì)性能提高、開(kāi)發(fā)效率提高有明顯幫助的技術(shù)點(diǎn)。 4、可開(kāi)發(fā)工具及流程控制,甚至重構(gòu)達(dá)到效率提升的。
七、安全相關(guān) 1、代碼安全 客戶端代碼除了底層代碼用C++以外,其它基本使用Lua腳本來(lái)開(kāi),所以腳本需要加密。以防止二次打包及非法行為。目前可以使用Cocos2d-x提供的xxtea加密策略。 2、支付安全 支付基本的參數(shù)不可暴露。
八、大廳架構(gòu) 是一個(gè)最小資源包,只有一個(gè)登錄到大廳的UI展示。可以不包括邏輯業(yè)務(wù)部分,然后再去熱更新部想要玩的部分,一些公用部分完全可以設(shè)計(jì)放在這個(gè)版本內(nèi)部。大體包括如下內(nèi)容: 1、BaseCore部分 2、賬號(hào)體系 3、熱更功能 4、大廳UI 5、可以自由配置相關(guān)的模塊來(lái)達(dá)到想要的包體 6、支付模塊的基礎(chǔ)部分
最理想化是可以如下操作,出某版本,后期想給這個(gè)版本加某個(gè)游戲,可以通過(guò)熱更新的方式去更新。
模塊化游戲大廳方案: 通過(guò)事件方式來(lái)注冊(cè)游戲,通過(guò)配置來(lái)定好游戲中包含哪些模塊,進(jìn)行事件注冊(cè),然后再大廳打開(kāi)模塊后發(fā)送相應(yīng)的事件去打開(kāi)模塊。
九、技術(shù)實(shí)現(xiàn)
9.1 技術(shù)選型及工程結(jié)構(gòu) 綜合選擇Cocos2d-x3.11.1版本,更新了ipv6及openssl等相關(guān)內(nèi)容。BaseCore版本我們用C++完成基本功能(暫時(shí)命名為theway),然后具體業(yè)務(wù)項(xiàng)目將theway引用作為依賴,并且業(yè)務(wù)開(kāi)發(fā)使用Lua腳本開(kāi)發(fā)。這樣將底層跟業(yè)務(wù)解耦。另外為整合多個(gè)游戲帶來(lái)最基本的技術(shù)上的支持。
9.2 自研引擎可行性 可以做成依賴項(xiàng)目,作為其他項(xiàng)目的底層,隨著項(xiàng)目不斷優(yōu)化和集成可以衍生成一個(gè)擁有我們自己知識(shí)產(chǎn)權(quán)的引擎項(xiàng)目。這樣底層修改或升級(jí),只需要做兼容即可,大不必讓業(yè)務(wù)開(kāi)發(fā)受限。同時(shí)可以整合各項(xiàng)目的開(kāi)發(fā)資源,提高開(kāi)發(fā)效率,產(chǎn)品質(zhì)量。
9.3 工具鏈開(kāi)發(fā) 作為商業(yè)開(kāi)發(fā),開(kāi)發(fā)工具的完善也是一項(xiàng)必不可少的環(huán)節(jié),目的是為了提高產(chǎn)品開(kāi)發(fā)的效率。例如我們利用工具提高開(kāi)發(fā)效率的一個(gè)實(shí)際例子。用Python生成協(xié)議Bean來(lái)直接序列化消息內(nèi)容,通過(guò)委托模式,業(yè)務(wù)模塊只需要關(guān)注發(fā)送,返回協(xié)議回調(diào)函數(shù)收到一個(gè)Table,十分的方便好用。后面可以將一些重復(fù)工作用工具去做。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注