一. 總覽
在Cocos2d-x-3.x引擎中,採用節點樹形結構來管理遊戲對象,一個遊戲可以劃分爲不同的場景,一個場景又可以分爲不同的層,一個層又可以擁有任意個可見的遊戲節點(即對象,遊戲中基本上所有的類都派生於節點類Node)。可以執行Action來修改遊戲節點的屬性,使其移動、旋轉、放大、縮小等等。
每一個時刻都有一個場景在獨立運行,通過切換不同的場景來完成一個遊戲流程,遊戲流程的管理由Director來執行,其基本框架類圖如下:
一,導演(Director)
一款遊戲好比一部電影,只是遊戲具有更強的交互性,不過它們的基本原理是一致的。所以在Cocos2dx中把統籌遊戲大局的類抽象爲導演(Director),Director是整個cocos2dx引擎的核心,是整個遊戲的導航儀,遊戲中的一些常用操作就是由Director來控制的,比如OpenGLES的初始化,場景的轉換,遊戲暫停繼續的控制,世界坐標和GL坐標之間的切換,對節點(遊戲元素)的控制等,還有一些遊戲數據的保存調用,屏幕尺寸的獲取等都要由Director類來管理控制的。
因爲Director是遊戲項目的總導演,會經常調用進行一些控制,所以該Director利用了單件設計模式,也就是項目裏取到的director都是同一個。用getInstance()方法取得Director的實例,具體的API可以參考相關文檔,就不做贅述了。
二,場景(Scene)
Scene場景也是cocos2dx中必不可少的元素,遊戲中通常我們需要構建不同的場景(至少一個),遊戲裏關卡、版塊的切換也就是一個一個場景的切換,就像在電影中變換舞臺和場地一樣。場景的一個重要的作用就是流程控制的作用,我們可以通過Director的一系列方法控制遊戲中不同的場景的自由切換。
下面是Director控制場景的常用方法:
runWithScene(Scene *scene )
啓動遊戲,並運行scene場景。本方法在主程序第一次啓動主場景的時候調用。如果已有正在運行的場景則不能調用該方法;會調用pushScene-->startAnimation。
· pushScene( Scene *scene )
· 將當前運行中的場景暫停並壓入到代碼執行場景棧中,再將傳入的scene設置爲當前運行場景,只有存在正在運行的場景時才調用該方法;
· replaceScene( Scene *scene )
· 直接使用傳入的scene替換當前場景來切換畫面,當前場景被釋放。這是切換場景時最常用的方法。
· popScene() 釋放當前場景,再從代碼執行場景中彈出棧頂的場景,並將其設置爲當前運行場景。如果棧爲空,直接結束應用。和PushScene結對使用
· end() 釋放和終止執行場景,同時退出應用
· pause() 暫停當前運行場景中的所有計時器和動作,場景仍然會顯示在屏幕上
· resume () 恢復當前運行場景的所有計時器和動作,場景仍然會顯示在屏幕上
同時場景是層的容器,包含了所有需要顯示的遊戲元素。通常,當我們需要完成一個場景時候,會創建一個Scene的子類,並在子類中實現我們需要的功能。比如,我們可以在子類的初始化中載入遊戲資源,爲場景添加層,啓動音樂播放等等。
三,層(Layer)
Layer是處理玩家事件響應的Node子類。與場景不同,層通常包含的是直接在屏幕上呈現的內容,並且可以接受用戶的輸入事件,包括觸摸,加速度計和鍵盤輸入等。我們需要在層中加入精靈,文本標籤或者其他遊戲元素,並設置遊戲元素的屬性,比如位置,方向和大小;設置遊戲元素的動作等。通常,層中的對象功能類似,耦合較緊,與層中游戲內容相關的邏輯代碼也編寫在層中,在組織好層後,只需要把層按照順序添加到場景中就可以顯示出來了。要向場景添加層,我們可以使用addChild方法。
addChild( Node child) addChild( Node child,int zOrder ) addChild( Node *child, int zOrder, int tag )
其中,Child參數就是節點。對於場景而言,通常我們添加的節點就是層。先添加的層會被置於後添加的層之下。如果需要爲它們指定先後次序,可以使用不同的zOrder值。tag是元素的標識號碼,如果爲子節點設置了tag值,就可以在它的父節點中利用tag值就可以找到它了。層可以包含任何Node作爲子節點,包括Sprites(精靈),Labels(標籤),甚至其他的Layer對象。
四,精靈(Sprite)
Cocos2d中的精靈和其他遊戲引擎中的精靈相似,它可以移動,旋轉,縮放,執行動畫,並接受其他轉換。Cocos2dx的Sprite由Texure,frame和animation組成,由openes負責渲染。主要的類關係如下: 簡單過程可描述爲:使用Texture2D加載圖片,可以用Texture2D生成對應的SpriteFrame(精靈幀),將SpriteFrame添加到Animation生成動畫數據,用Animation生成Animate(就是最終的動畫動作),最後用Sprite執行這個動作。
看完這段話大家估計會感覺不知所云,是的,我看到這段話也是這樣的感覺,這話比文言文都難懂呀,那麼我們該如何理解精靈呢,這個很好解決,我來給大家總結一下就行了,當然我總結的就相對通俗易懂多了,哈哈。
我對於精靈的理解:所謂精靈,其實就是一個四邊形,這個四邊形可以加載顯示單圖片和序列幀圖片。同時它的四個頂點的位置,色彩,透明度等信息可以被我們控制和改變。精靈,是我們對於圖型圖像進行控制的基礎操作物體。
看了總結是不是感覺對精靈有點清晰的認知了呢。
五,相互之間的關係
通過上面的介紹大家應該對Director ,Scene ,Layer,Sprite有了初步的認識,那麼它們是如果通過聯繫組合來爲大家呈現一個絢麗多彩的遊戲的呢,這個我們就通過代碼來看一下。我們新建一個叫HelloLesson9的工程,具體怎麼新建工程就不在講解了,創建完成後打開Appdelegate,找到如下代碼:
// 創建Scene
auto scene = HelloWorld::createScene();
//通過Director運行Scene
director->runWithScene(scene);
我們可以看到,我們通過HelloWorld的createScene()創建了一個Scene,具體createScene()方法是如何返回一Scene我們暫且不管,我們這裏先來看看下面的一句代碼,通過director對象調用了runWithScene方法,該方法我們介紹Scene的時候都有講到,介紹首次運行Scene時被用到的,這句代碼執行之後,Scene就會被加載到遊戲中做顯示了。下面我們接着來看createScene(),進入HelloWorldScene.cpp查看createScene()方法的源碼,可以看到:
Scene* HelloWorld::createScene()
{
// 創建Scene
auto scene = Scene::create();
// 創建Layer對象
auto layer = HelloWorld::create();
// 把Layer添加到Scene裏,Scene就是Layer的容器,可以添加很多Layer
scene->addChild(layer);
// 把Scene返回
return scene;
}
通過代碼的注釋大家應該能看懂。這裏可以看到先創建了一個Scene對象,Scene主要用來當做Layer的容器,然後創建了一個Layer,並把該Layer添加到了Scene上,當然這個Layer在調用create()函數的時候就會調用到本身的Init()方法,在init方法中可以完成一些初始化的工作,例如添加一些sprite,例如去加載一個CocosStudio到處的創建文件.csb。然後當我們的場景運行起來的時候被添加的這些遊戲元素就能顯示出來了。
通過上面的講解我們可以總結一下:Director使用來運行,跳轉Scene的,也就是說Director用來管理Scene,而Scene又是Layer的容器,創建的Layer只有添加到Scene上才能被最終顯示出來,當然Scene可以同時添加很多Layer。Layer是作爲顯示的面板來使用的,可以添加Sprite,Label,Menu,Button,等等很多類型的遊戲元素,通過這些遊戲元素來展現我們的遊戲,最終也就通過Director,Scene,Layer,Sprite這四個組件的組合創造出了繽紛多彩的遊戲世界。