【深入Cocos2d-x】使用MVC架構搭建遊戲Four
喜歡Four這個專案,就趕快在GitHub上Star這個專案吧!
喜歡我的文章,來微博關注我吧:王選易在學C艹
專案起源
專案Logo:
下面是該遊戲的專案地址,各位想參考原始碼的同學可以到我的GitHub上下載該專案的原始碼。
我做這個專案的原始目的是實驗MVC在遊戲中的應用。
MVC經常被使用在Web框架中,包括J2EE,RoR和.Net中都對MVC模型進行了框架層面上的封裝,以便程式設計師可以簡單方便地作出結構良好的Web應用。
Cocos2d-x本身並沒有提供內建的MVC支援,但是,我們還是可以在遊戲中基於MVC架構來設計遊戲。在這篇博文中,我將向大家展示一下我是如何使用MVC架構來塔尖
遊戲情景
Four這個遊戲的創意來自一個叫做走四棋的傳統遊戲,走四棋規則的詳細介紹在這裡:走四棋的百度百科。
下面我簡單談一下這個面板遊戲(board game)的一些特性
- 一個4行4列的棋盤(Game Board)
- 棋盤上會有一些“棋子”(Game Piece),每一個方格上只能放一個棋子(Game Piece)。
- 遊戲初始化時,棋盤的上面四格和下面四格分別有4個黑子和四格白子
- 玩家可以通過話筒使棋子在棋盤上發生移動,從而觸發吃子和勝利等事件。
- 當遊戲中出現一個橫行或者一個豎列的棋子排布變為兩黑一白或者兩白一黑時,即可吃掉一子。
- 當一方(黑或白)的棋子被吃到只剩一個之後,這一方被記為失敗
舉個例子,下面這幅圖即為遊戲過程中的一幅圖。在下面的遊戲過程中,位於(1,0)位置的黑子向左移動到(0,0)的位置後即可吃掉白子。
Cocos2d-x提供的工具
Cocos2d-x有這樣一些主要的類,CCSprite,CCLayer,CCScene,CCNotificationCenter。我們會使用這些類進行遊戲中MVC架構的搭建,如果你對這些類的作用不熟,請參考我的這篇博文【Cocos2d-x-基礎概念】Director Scene Layer and Sprite。
我們一般的遊戲流程是
- 通過AppDelegate初始化第一個CCScene。
- 在第一個CCScene建立多個CCLayer。並控制好CClayer的疊加層次(zOrder)。
- 在CCLayer中新增各種CCSprite或者CCLabelAtlas或者粒子效果。
- 在CCLayer層註冊觸控事件的監聽,並且在CCLayer的實現中寫出相應的callback函式,對CCLayer的Child Node進行相應的邏輯處理。
這個過程看起來十分簡單,並且可以十分快速地做出遊戲。但是其缺陷就在於在CCLayer中我們做了太多的事情。CCLayer同時承擔了邏輯層和表示層的任務。不符合我們上文中提到的關注點分離的原則。如果遊戲中有較為複雜的狀態轉換時就捉襟見肘了。
專案的檔案目錄
下面是該遊戲專案的目錄結構,我們接下來對這幾個資料夾進行分別的講解:
下面是該專案的一個簡單的類圖
在類圖中,虛線代表的是通過訊息機制進行溝通,而在Cocos2d-x中,這種溝通是通過CCNotificationCenter來實現的。
Model(模型)
Model在遊戲中代表的是訊息驅動的有限狀態機,Model會接受Controller層傳送的訊息,並根據訊息來更改自己的內部資料,然後把內部資料改變這一訊息傳送給View,通知它更新。
Model在Cocos2d-x對應的是哪個類呢?
很遺憾,但是Cocos2d-x並沒有提供狀態機的feature,所以我們需要自己實現一個Model類,在Model類中,需要自己實現諸如狀態轉換和訊息處理等功能。例如在我的Model類中,我提供瞭如下介面。
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(); };
注意以下幾點:
- 讓Model類繼承CCObject,是為了與Cocos2d-x自身的記憶體管理系統一致。
- onMessage中,我們做的事情就是首先找到當前狀態在msg情況下的狀態轉換。在狀態轉換後,通過
CCNotificationCenter
傳送一條訊息通知遊戲中的其他元件更新邏輯。 - waitAction中,我們是在處理一種非同步的狀態轉換,比如一個棋子在移動時就會經歷這樣的狀態轉換start->moving->end,那麼在移動結束後,View就要傳送一條類似END_MOVE的訊息來通知Model更新自己的狀態。
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
中,定義了遊戲中期盤的寬,搞和一些常用的資料結構。
參考文獻
相關推薦
【深入Cocos2d-x】使用MVC架構搭建遊戲Four
喜歡Four這個專案,就趕快在GitHub上Star這個專案吧! 喜歡我的文章,來微博關注我吧:王選易在學C艹 點我下載 專案起源 專案Logo: 下面是該遊戲的專案地址,各位想參考原始碼的同學可以到我的GitHub上下載該專案的原始碼。 專案主頁 我做這個專案的原始目的是實驗M
【Cocos2d-x】坐標系和圖層
pac 多說 pan art world 地圖 分辨 play instance 在Cocos2D-X中,存在四種坐標系: 1、OpenGL坐標系:該坐標系原點在屏幕左下角。x軸向右,y軸向上。這也就是cocos2dx中用到的坐標系所以沒啥好說的。 2、屏幕坐標系(UI
【iOS-cocos2d-X 遊戲開發之四】Cocos2dX建立Android NDK新專案並編譯匯入Eclipse中正常執行!
站文章均為 李華明Himi 原創,轉載務必在明顯處註明: 轉載自【黑米GameDev街區】 原文連結: http://www.himigame.com/android-game/645.html ☞ 點選訂閱 ☜ 本部落格最新動態
【Cocos2d-x】截圖分享功能
Cocos2d-x截圖實現 #include "cocos2d.h" USING_NS_CC; // 設定紋理寬、高、畫素質量 CCRenderTexture* tx = CCRenderTexture::create(CCDirector::sharedDirec
【平凡曉聲 Cocos2d-x】虛擬按鍵控制精靈移動1
虛擬按鍵控制精靈移動1 最近想做過街機類的遊戲,做這類遊戲,首先我想到的就是精靈的移動,就是當按鍵按下時,精靈進行移動,當按鍵擡起時,精靈停止移動。 查閱了相關資料,最後整理出了兩種方法分享給大家,廢話不多說了,開幹。 1.通過touch點選事件和sche
【Cocos2d-x】圖片描邊的一種比較好的shader實現方法
轉載: http://blog.csdn.net/u011281572/article/details/44999609 圖片描邊需求如下: 1. 可指定描邊寬度2. 可指定描邊顏色3. 可用於字型 圖片描邊我所知道的方式有以下幾種: 1. Cocos2d-x 3.x中,
【Cocos2D-X 】初窺門徑(1) 製作一個動態的精靈
原理: Cocos2D中有個導演控制整個遊戲流程,導演將場景新增到螢幕上,場景中有各種各樣的演員。 先通過顯示一張圖片來看看Cocos2D遊戲的流程: AppDelegate.cpp bool AppDelegate::applicationDidFinishLaunch
【Cocos2d-x】之編譯so檔案出錯
現在用的是cocos2d-x3.6版本,這個版本新建的工程第一次在eclipse上跑的時候,會出現找不到Cocos2d-x在Android平臺的Java類,錯誤如圖: 這些類位於:<遊戲工程路
【Cocos2D-X 】初窺門徑(5)CCAction:動作
//移動到,1s, pRole->runAction(CCMoveTo::create(1,ccp(300,300))); //跳躍到,1s,高度50,分為5步 pRole->runAction(CCJumpTo::create(1,ccp(300,300),50,5)); //放
【Cocos2d-x】物理引擎使用入門
相關概念 什麼是物理引擎? 科學模型:科學研究中對事物的合理簡化。 物理引擎是一個計算機程式模擬牛頓力學模型,使用質量、速度、摩擦力和空氣阻力等變數。 可以用來預測這種不同情況下的效果。它主要用在科學模擬和電子遊戲中。 一般,物理引擎只負責物理計算,而不進行畫面渲染。
【quick-cocos2d-x 遊戲開發】quick cocos2dx 3.2最穩定版 建立工程+sublime除錯執行
測試環境mac quick cocos2dx 3.2 quick cocos2dx 3.2版本已經差不多了 已經可以建立工程使用了,看下流程 1.最新版quick cocos2dx 3.2 建立工程,編譯,執行 1.1下載 按照README配置工程,執行player3
【Cocos2D-X 】初窺門徑(10)解決中文亂碼
用資原始檔儲存字串,格式UTF-8,這樣讀取xml檔案,然後顯示就不會亂碼了。 這樣做還有一個好處就是方便以後國際化。 xml檔案: <dict> <key>Hello</key> <string>Hi~可以正常顯示中
【加快cocos2d-x編譯速度】cocos2d-x編譯專案時避免拷貝資料夾和庫
http://codingnow.cn/cocos2d-x/928.html 本文參考自子龍山人的部落格,跟他的方法也有少許的不同,自己用著舒心才是最重要的。cocos2d-x的版本更新太快了,本文使用的是最新的cocos2d-x 2.0.4版本,IDE是vs2010
【cocos2d-x】建構函式與初始化
出自圖書《製作自己的捕魚達人》 在cocos2d-x中建立物件的方法與C++開發者的習慣不同,在C++中,我們只需要呼叫類的建構函式即可建立一個物件,即可直接建立一個棧上的值物件, 也可以使用new操作符建立一個指標,指向堆上的物件,而在cocos2d-
【Cocos2D-X 】初窺門徑(2) 場景的切換及特效
//CCTransitionJumpZoom::transitionWithDuration(t, s);//跳躍式,本場景先會縮小,然後跳躍進來 //CCTransitionFade::transitionWithDuration(t, s);//淡出淡入,原場景
【cocos2d-x】cocos2d-x 3.2 在 NDK10下編譯出錯的解決方法
最近使用cocos2d-x 3.2 在NDK10 版本下打包APK,出現了一個特別奇怪的錯誤。 1. /Users/minggo/SourceCode/cocos2d-x/build/../cocos/./3d/CCBundleReader.cpp:94:
【深入理解C#】第2章 C#1所搭建的核心基礎
class thread類 委托 組類型 賦值 需要 派生 聲明 -- 1)委托類型 基本理解: 類型安全的函數指針。 可以間接完成某種操作,雖增加了復雜性,但也增加了靈活性。 可以看作方法的占位符。 為什麽要用委托: 可以傳遞函數意味著可以將業務邏輯作為參數傳遞。 間接
【深入JAVA EE】Spring配置文件解析
article per posted 別名 utf-8 div back port clu 在閱讀的過程中有不論什麽問題,歡迎一起交流 郵箱:[email protected]/* */ QQ:1494713801 一、S
【編程思想】【設計模式】【結構模式Structural】MVC
style ring gui \n http PE struct class console Python版 https://github.com/faif/python-patterns/blob/master/structural/mvc.py #!/usr/b
【深入學習Redis】Redis內存模型
table 惰性 IV vbo 都是 設計 eqv http content 前言 Redis是目前最火爆的內存數據庫之一,通過在內存中讀寫數據,大大提高了讀寫速度,可以說Redis是實現網站高並發不可或缺的一部分。 我們使用Redis時,會接觸Redis的5種對象類型