喜歡Four這個項目,就趕快在GitHub上Star這個項目吧!node
喜歡個人文章,來微博關注我吧:王選易在學C艹git
點我下載程序員
##項目起源github
項目Logo:設計模式
下面是該遊戲的項目地址,各位想參考源代碼的同窗能夠到個人GitHub上下載該項目的源碼。數組
項目主頁數據結構
GitHub地址架構
bug反饋及建議mvc
我作這個項目的原始目的是實驗MVC在遊戲中的應用。app
Model-View-Controller(MVC)是一種組合設計模式,它體現了一種關注點分離(Separation of concerns,SoC)的思想。MVC主要把邏輯層和表現層進行了解耦,將一個問題劃分紅了不一樣的關注點。加強了應用的穩定性,易修改性和易複用性。
MVC常常被使用在Web框架中,包括J2EE,RoR和.Net中都對MVC模型進行了框架層面上的封裝,以便程序員能夠簡單方便地做出結構良好的Web應用。
Cocos2d-x自己並無提供內置的MVC支持,可是,咱們仍是能夠在遊戲中基於MVC架構來設計遊戲。在這篇博文中,我將向你們展現一下我是如何使用MVC架構來塔尖Four這個遊戲的。
##遊戲情景
Four這個遊戲的創意來自一個叫作走四棋的傳統遊戲,走四棋規則的詳細介紹在這裏:走四棋的百度百科。
下面我簡單談一下這個面板遊戲(board game)的一些特性
舉個例子,下面這幅圖即爲遊戲過程當中的一幅圖。在下面的遊戲過程當中,位於(1,0)位置的黑子向左移動到(0,0)的位置後便可吃掉白子。
##Cocos2d-x提供的工具
Cocos2d-x有這樣一些主要的類,CCSprite,CCLayer,CCScene,CCNotificationCenter。咱們會使用這些類進行遊戲中MVC架構的搭建,若是你對這些類的做用不熟,請參考個人這篇博文【Cocos2d-x-基礎概念】Director Scene Layer and Sprite。
咱們通常的遊戲流程是
這個過程看起來十分簡單,而且能夠十分快速地作出遊戲。可是其缺陷就在於在CCLayer中咱們作了太多的事情。CCLayer同時承擔了邏輯層和表示層的任務。不符合咱們上文中提到的關注點分離的原則。若是遊戲中有較爲複雜的狀態轉換時就捉襟見肘了。
##項目的文件目錄
下面是該遊戲項目的目錄結構,咱們接下來對這幾個文件夾進行分別的講解:
下面是該項目的一個簡單的類圖
在類圖中,虛線表明的是經過消息機制進行溝通,而在Cocos2d-x中,這種溝通是經過CCNotificationCenter來實現的。
##Model(模型)
Model在遊戲中表明的是消息驅動的有限狀態機,Model會接受Controller層發送的消息,並根據消息來更改本身的內部數據,而後把內部數據改變這一消息發送給View,通知它更新。
Model在Cocos2d-x對應的是哪一個類呢?
很遺憾,可是Cocos2d-x並無提供狀態機的feature,因此咱們須要本身實現一個Model類,在Model類中,須要本身實現諸如狀態轉換和消息處理等功能。例如在個人Model類中,我提供了以下接口。
<!-- lang: cpp --> class Model : public CCObject { public: // 添加一條狀態轉換,from-起始狀態,msg-接收的消息,to-終結狀態,在msg發生時會發生狀態轉換 Model* addTransition(const string& from, const string& msg, const string& to); // 檢查當前狀態機可否發生msg對應的狀態轉換 bool checkMessage(const string& msg); // 觸發msg對應的狀態轉換 void onMessage(const string& msg); void onMessage(const string& msg, CCObject* o); // 等待某個CCAction結束後發送一條消息。 void waitAction(cocos2d::CCNode* node, cocos2d::CCFiniteTimeAction* action, const string& msg); // 獲得當前狀態名稱 const char* getState(); };
注意如下幾點:
CCNotificationCenter
發送一條消息通知遊戲中的其餘組件更新邏輯。Model不會持有View,因此View都是經過消息來得到Model更新的事件的。
咱們在編寫遊戲時,應該先編寫Model,而後經過測試來保證Model的正確性。
以後,咱們去寫View的時候,實際就是對Model這個狀態機發送的各類消息的回調函數的編寫了。
這樣就講表示層和邏輯層分離開,能夠方便地單獨測試每一個模塊,可維護性大大提升。
###邏輯數據和實際數據
在編寫Model的時候,咱們常常會遇到這樣的問題,就是Model中的數據是否應當與View中的數據保持一致。
好比:在View層的棋子的位置信息是否應該和Model層的位置信息保持一致?
其實,真實狀況就是,這要看Model層的 計算使用那種數據形式更加方便,好比在Model中,咱們會把棋盤轉化爲一個二維數組,這樣在AI運算,邏輯判斷時,更加有利,因此棋子的邏輯位置和實際位置必然是不一樣的。
再好比,不少時候遊戲中的物理引擎的計量單位是釐米,米。而不是OpenGL中的座標。這也是爲了邏輯運算的方便。
可是有些數值,咱們會讓它保持一致,好比人物的屬性等等。
##View(視圖)
View在遊戲中表明的是Model消息的接受者,在Cocos2d-x中,View通常是指CCLayer的子節點,即CCSprite,CCLabelAtlas,CCMenuItem,Particle System(粒子系統)等等。
它們會重載onEnter函數,在onEnter中註冊本身對某個Message的監聽。同時在onExit函數中將全部監聽清除。(清除監聽很重要,不然會出現很可怕的野指針問題)。
##Controller(控制器)
Controller在遊戲中負責將用戶觸摸事件轉化爲邏輯事件(即咱們上文中所說的消息),同時要對用戶觸摸事件中的信息進行正規化,而且通知變動。
Controller在Cocos2d-x中通常用CCLayer 來實現,由於CCLayer天然地繼承了CCTouchDelegate這一接口,自己就能夠觸摸事件,因此我在這個遊戲中全部的XXXController都是繼承自CCLayer。
Controller另外一個很重要的職責,就是建立View和Model,由於Controller至關於Model和View的一箇中間層,因此天然Controller會同時持有View和Model的應用,來方便地傳遞數據。
##Protocol(協議)
Protocol中定義了一些Model,View和Controller中共享的數據,
Message.h
中,就定義了遊戲中各類類型的消息,Tag.h
中,就定義了遊戲中一些Node的Tag,其實Tag這個定義不是很準確,其實這裏的Tag指的是惟一標識CCNode的一個ID。ChessboardProrocol.h
中,定義了遊戲中期盤的寬,搞和一些經常使用的數據結構。##參考文獻