*一個游戲引擎就是一個可以提供大多游戲常用功能的軟件作品。你之前也許聽到過將它稱之為API或者框架。但在本書中我們會使用游戲引擎這個比較正式的術語。
通常游戲引擎中都包含這些組件,比如:渲染器,2d/3d圖形,碰撞檢測,物理引擎,聲音,控制器,動畫等。
*Cocos2d-x提供了Scene
, Transition
, Sprite
, Menu
, Sprite3D
, Audio
等許多對象。你創建游戲所需要的內容都在這了。
主要組件
*Cocos2d-x的核心類為 Scene
, Node
, Sprite
, Menu
和Action
對象。
導演類
Cocos2d-x使用Director
(導演)的概念。是的,就像拍電影一樣!
Director
類控制着游戲整體並通知游戲接下來需要做什么。
把你自己當成影片的監制人,你肯定會通知導演(Director
)該如何做!
Director
導演的一個通常作用是控制Scene
切換和切換效果。
導演(Director
)是一個共享的單例對象,你可以從代碼的任何地方調用。
這里是一個典型游戲的流程圖。導演 (Director
)通過這個流程圖來對游戲進行調渡並決定了游戲的標准:
場景
游戲中你可能需要一個主菜單,幾個關卡和一個結束場景。
你該如何將這些內容單獨的分開來呢?是的,這就需要Scene
。
回想一下你喜歡的電影,你會發現它很顯示的划分出了一些場景,或者單獨的故事劇情。
如果我們按照這種思路來處理游戲,不管游戲有多么簡單但我們應該想出至少有幾個場景。
場景都由Renderer
進行繪制。Renderer
可以用來繪制精靈或者其它對象到場景中。為了更好的理解這點我們需要了解一些關於_Scene Graph_的知識。
場景圖
_scene graph_是一個用來存儲場景圖形的數據結構。
_scene graph_由樹節點構成。(它雖然叫screne graph,但它實際上是用樹形結構來存儲)。
由於_Scene Graph_是樹形結構;你可以對它進行遍歷。Cocos2d-x使用了_in-order walk_算法。_in-order walk算法的流程如圖所示,從根節點開始,然后到右邊的樹。由於右邊的節點是最后繪制的,所以它會首先被顯示到場景中。
//這里有疑問;
_scene graph_很容易理解,讓我們來對圖中所示的場景進行分解:
將上面的場景表示為一個樹形,可以簡化為如下:
另一個需要注意的地方是,_z-order_Z軸為負數的元素會出現在樹的左側,而_z-order_Z軸為正數的會出現在樹的右側。
當在場景中添加結點的時候需要注意這一點。當然你可以在任意的地方添加節點元素它們會被按鈕Z軸的大小自動排序。
在這個概念的基礎上,我們可以把Scene
的視為一個Node
對象。
先暫時不看上一個場景,來看一下_scene graph_如何利用_z軸_來布局Scene
:
圖中左邊的場景是由許多節點對象組成的,但每個對象都處在不同的_z-order_Z軸上。
在Cocos2d-x中,可以通過API中的addChild()
方法來創建_scene graph_場景
// Adds a child with the z-order of -2, that means
// it goes to the "left" side of the tree (because it is negative)
scene->addChild(title_node, -2);
// When you don't specify the z-order, it will use 0
scene->addChild(label_node);
// Adds a child with the z-order of 1, that means
// it goes to the "right" side of the tree (because it is positive)
scene->addChild(sprite_node, 1);
精靈
精靈就是游戲中在場景里進行移動的對象。當你操縱一個精靈的時候,它就是一個精靈。如果你不對它進行操作,那它就是一個節點Node
。
_Sprites_精靈很容易創建,它具有很多屬性,比如:坐標position
,翻轉rotation
,縮放scale
,透明度opacity
,顏色color
等。
// This is how to create an sprite
auto mySprite = Sprite::create(
"mysprite.png"
);
// this is how to change the properties of the sprite
mySprite->setPosition(Vec2(500, 0));
mySprite->setRotation(40);
mySprite->setScale(2.0);
// sets scale X and Y uniformly
mySprite->setAchorVec2(0, 0);
下面我們來解釋每個屬性的作用,通過本章的示例代碼來思考下面的截圖:
通過代碼 mySprite->setPosition(Vec2(500, 0));
將坐標進行重新設置,如圖:
看一下發生了什么。Sprite
的坐標從它原有的坐標被移動到了我們設定的新坐標。
通過代碼mySprite->setRotation(40);
對精靈的翻轉進行設定,如圖:
看一下發生了什么。Sprite
精靈被翻轉了我們所設定的角度。
通過代碼mySprite->setScale(2.0);
將精靈進行縮放,如圖:
同樣地,我們可以發現精靈的大小被改變了。
最后,所有的節點Node
對象(注意Sprite
精靈類是Node
節點類的子類)都有一個稱為錨點的值。我們之前還沒有提過這個概念,現在時機正好。你可以將錨點想象為在對精靈進行坐標點設定的時候精靈所自身使用的坐標點。
通過代碼mySprite->setAchorVec2(0, 0);
將游戲中的精靈錨點設定為(0,0)坐標,那么所有使用代碼setPosition()
進行坐標設定的精靈都會以自身的左下角來進行對齊。讓我們來試一下:
注意觀察每個圖像中的紅點。這個紅點就是精靈的錨點位置!
你會發現錨點對節點來說是非常有用的。你甚至可以通過調整精靈的錨點來模擬動態效果。
現在我們已經可以很好地使用精靈了。那么該如何讓這些精靈按照一定的時間間隔自動的進行播放呢?繼續向下看。
動作
創建Scene
場景,添加Sprite
精靈對象到屏幕上只是其中一部分。
游戲之所以稱為游戲就是我們需要讓精靈運動起來!Action
動作游戲中的一部分。_Actions_動作類可以讓Node
節點對象按時間進行運動。
你可以創建一個Actions
動作序列Sequence
並且按順序播放。你可以通過改變Node
節點屬,坐標,角度,縮放。比如說這些動作:MoveBy
,Rotate
, Scale
。所有的游戲都使用動作類Actions。
Action的創建與使用;
auto mySprite = Sprite::create(
"Blue_Front1.png"
);
// Move a sprite 50 pixels to the right, and 10 pixels to the top over 2 seconds.
auto moveBy = MoveBy::create(2, Vec2(50,10));
mySprite->runAction(moveBy);
// Move a sprite to a specific location over 2 seconds.
auto moveTo = MoveTo::create(2, Vec2(50,10));
mySprite->runAction(moveTo);
序列和Spawns
一個序列Sequence
就是多個動作按鈕一定順序進行排列。需要按反方向來播放序列動作?也沒問題,Cocos2d-x也支持這個操作。
看一下面的例子,通過序列Sequence
逐步移動一個精靈Sprite
:
這個Sequence
很容易創建:
auto mySprite = Node::create()
// move to point 50,10 over 2 seconds
auto moveTo1 = MoveTo::create(2, Vec2(50,10));
// move from current postion by 100,10 over 2 seconds
auto moveBy1 = MoveBy::create(2, Vec2(100,10));
// move to point 150,10 over 2 seconds
auto moveTo2 = MoveTo::create(2, Vec2(150,10));
// create a delay
auto delay = DelayTime::create(1);
mySprite->runAction(Sequence::create(moveTo1, delay, moveBy1, delay->clone(), moveTo2, nullptr));
Spawn
。
Spawn
會在同一時間播放所有指定的動作。有一些可能比別的稍長一些,所以出現這種情況動作的播放不會在同一時間完成。
auto myNode = Node::create()
auto moveTo1 = MoveTo::create(2, Vec2(50,10));
auto moveBy1 = MoveTo::create(2, Vec2(100,10));
auto moveTo2 = MoveTo::create(2, Vec2(150,10));
myNode->runAction(Spawn::create(moveTo1, moveBy1, moveTo2, nullptr));
父類和子類之間的繼承關系
Cocos2d-x使用Parent and Child
繼承。也就是說父類中的屬性也適用於他們的子類。考慮一個Sprite
對象和它的子類對象Sprite
:
當改變父類中的精靈角度時,子類的角度也會隨之進行變化: