write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie
雖然很早就想用做一個完整游戲來完成此教程,但是在做什么游戲的問題上很糾結,太大太好的游戲太費精力,太小的游戲又不足以展示Orx的特點,選來選去也沒有自己感覺最合適的,最后還是選擇打磚塊吧,此游戲雖然不能展示Orx的全部特點,但是很好的展示了其內嵌物理引擎的特點。因為Orx內嵌Box2D物理引擎,所以在游戲中使用物理,從來沒有這么方便過,也許,哪天我該寫一篇用Cocos2D+Box2D的類似文章來做比較。
Orx 中的Object概述
在Orx中一個Object到底表示什么?簡單的說,表示一切。一切有形的無形的,可見的不可見的東西。在Orx中,所有所有的概念全部歸結于 Object。所有其他的東西,都是Object的屬性。包括通常概念里面的sprite,animation等等,在Orx中還包括特效(fx),物理屬性等。在幾乎所有的2D游戲引擎中,幾乎都是是Sprite為基礎的,而在Orx中,是以Object為基礎的。
顯示一個 Object
在幾乎所有的2D游戲引擎中,幾乎都是是Sprite為基礎的,所以最基本的操作都是顯示一個Sprite,那么,換到Orx中,最基礎的那就是顯示一個 Object了。
其實,在原來《
站在巨人的肩膀上開發游戲(2) -- Orx入門引導及Hello World
》中,我們已經顯示過一個 Object了,沒錯,那個Hello World的文字就是一個Object.........只不過其圖形是顯示文字而已。所以,我們創建Hello World的時候,調用的接口是
orxObject_CreateFromConfig
。
要將其換成顯示圖形,只需要改配置,將其顯示成一個圖形即可,因為是做打磚塊游戲,這里,我顯示一個球。(這里的資源全部來自于《
How To Create A Breakout Game with Box2D and Cocos2D Tutorial
》)順面可以將Orx版本的程序與Cocos2D + Box2D(另外一個我非常喜歡的組合)做比較。
原代碼的改動僅出于代碼可讀性考慮,將HelloWorld改為Ball,Orx的特點之一,不改代碼,你甚至可以使用原來編譯好的Hello World程序(必須是教程1老的那個,教程2新的那個我做了特殊處理),只需要將新的配置中的Ball改為HelloWorld即可。當然,出于可讀性,這樣做不自然,但是我還是提及這樣做的可能性。
新添加配置如下:
[Ball]
Graphic =
BallGraphic
Position =
(0.0, 0.0, 0.0) ;球所在的位置
[BallGraphic]
Texture =
data/ball.png ;球圖形的png文件的位置
Pivot =
center
原來的代碼如下:
// Init game function
orxSTATUS GameApp::InitGame()
{
orxSTATUS result = orxSTATUS_SUCCESS;
// Creates viewport
if
( orxViewport_CreateFromConfig(
"Viewport"
) ==
NULL
) {
result = orxSTATUS_FAILURE;
}
if
(orxObject_CreateFromConfig(
"Ball"
) ==
NULL
) {
result = orxSTATUS_FAILURE;
}
// Done!
return
result;
}
然后,就能顯示出個球了。(顯示個球-_-!)
就這么一個Object顯示出來以后,就可以繼續自由發揮了,很多的想象空間。
比如Scale = XXX調整球的大小。
比如Speed = (xxx, xxx, xxx) 給球初始速度,
(上面的屬性都添加到
[Ball]
段)
按照上面的方法,按打磚塊游戲的特點,添加磚塊及paddle。
配置:
[Ball]
Graphic =
BallGraphic
Position =
(0.0, 180.0, 0.0)
[BallGraphic]
Texture =
data/ball.png
Pivot =
center
[Paddle]
Graphic =
PaddleGraphic
Position =
(0.0, 230.0, 0.0)
[PaddleGraphic]
Texture =
data/paddle.png
Pivot =
center
[Blocks]
ChildList =
Block1 # Block2 # Block3 # Block4
[Block1]
Graphic =
BlockGraphic
Position =
(-50.0, -30.0, 0.0)
[Block2]
Graphic =
BlockGraphic
Position =
(50.0, -30.0, 0.0)
[Block3]
Graphic =
BlockGraphic
Position =
(-50.0, 30.0, 0.0)
[Block4]
Graphic =
BlockGraphic
Position =
(50.0, 30.0, 0.0)
[BlockGraphic]
Texture =
data/block.png
Pivot =
center
代碼:
// Init game function
orxSTATUS GameApp::InitGame()
{
orxSTATUS result = orxSTATUS_SUCCESS;
// Creates viewport
if
( orxViewport_CreateFromConfig(
"Viewport"
) ==
NULL
) {
result = orxSTATUS_FAILURE;
}
if
(orxObject_CreateFromConfig(
"Ball"
) ==
NULL
) {
result = orxSTATUS_FAILURE;
}
if
(orxObject_CreateFromConfig(
"Paddle"
) ==
NULL
) {
result = orxSTATUS_FAILURE;
}
if
(orxObject_CreateFromConfig(
"Blocks"
) ==
NULL
) {
result = orxSTATUS_FAILURE;
}
// Done!
return
result;
}
代碼實在就是沒有太多好說的了,在Orx中,永遠是配置復雜,代碼簡單。說說配置中的新東西,我在這里用
[Blocks]
ChildList =
Block1 # Block2 # Block3 # Block4
的形式+一行創建Blocks的代碼,來完成了4個磚塊的創建。這是Orx中使用子列表的一種方式。
效果如下:(我把窗口大小也改了)
是不是有那么一點意思了?
到目前為止,我們學到什么了?4行配置。。。。。。。。。。
且只有Graphic加
Texture算是新內容。
只要這些,你通過position就可以完成你想要的任何圖形布局了。
當然,其實遠遠不止這些,請參考Orx的WIKI獲取更多的信息:
物理的加入
好了,現在是添加真的游戲內容的時候了。光是靜態圖形可做不了游戲。
在打磚塊的游戲中,很重要的就是球的碰撞,反彈,以及碰撞的檢測了。由于Orx中內嵌了Box2D引擎,我們能夠很方便的使用,我多次提到是內嵌,而不是外掛,不是如Cocos2D那種僅僅包含一個Box2D,然后需要你調用Box2D的API去完成的那種,事實上,你可以根本不知道Box2D是啥。(其實個人感覺,了解Box2D的相關概念是必要的,不然怎么知道各個屬性應該怎么配置啊)
首先,物理世界的加入:
[Physics]
DimensionRatio =
0.1
WorldLowerBound =
(-300.0, -300.0, 0.0)
WorldUpperBound =
(300.0, 300.0, 0.0)
這是必須的,似乎屬于Box2D為了優化而添加的,Orx為了靈活,沒有自動的去配置這些屬性,一般而言,將其設為包含整個游戲屏幕即可。(稍微大一點點)配置的是一個矩形的左上角和右下角。(注意Orx的坐標系啊)
然后,為各個物體添加物理屬性,最主要的是Body段的屬性:
[Ball]
Graphic =
BallGraphic
Body =
BallBody
Speed =
(0, -40, 0)
Position =
(0.0, 180.0, 0.0)
[BallGraphic]
Texture =
data/ball.png
Pivot =
center
[BallBody]
Dynamic =
true
PartList =
BallPartTemplate
[BallPartTemplate]
Type =
sphere;
Friction =
0.0;
Restitution =
1.0;
Density =
1.0;
SelfFlags =
0x0001;
CheckMask =
0x0001;
Solid =
true;
注意Ball的中添加了一個
Body =
BallBody
,然后所有的物理部分都寫在了BallBody和BallPartTemplate中。先說明一下,之所以我把part叫template,而且Orx的作者添加了這樣一個新的段來表示物理部分,包括命名為part,是因為Orx允許一個body有多個part組合成一個object的物理。這在某些時候也極為有用。比如希望有個組合圖形,一個part無法表示的時候。
至于各個物理的屬性的含義,推薦先去了解一下
Box2D 的各個定義
。要圖省事,看看
Orx的說明
也行。
然后,如法炮制,基本的意思就有了。
[Paddle]
Graphic =
PaddleGraphic
Body =
PaddleBody
Position =
(0.0, 230.0, 0.0)
[PaddleGraphic]
Texture =
data/paddle.png
Pivot =
center
[PaddleBody]
Dynamic =
false
PartList =
PaddlePartTemplate
[PaddlePartTemplate]
Type =
box;
Friction =
0.0;
Restitution =
1.0;
Density =
1.0;
SelfFlags =
0x0001;
CheckMask =
0x0001;
Solid =
true;
[Blocks]
ChildList =
Block1 # Block2 # Block3 # Block4
[Block1]
Graphic =
BlockGraphic
Body =
BlockBody
Position =
(-50.0, -30.0, 0.0)
[Block2]
Graphic =
BlockGraphic
Body =
BlockBody
Position =
(50.0, -30.0, 0.0)
[Block3]
Graphic =
BlockGraphic
Body =
BlockBody
Position =
(-50.0, 30.0, 0.0)
[Block4]
Graphic =
BlockGraphic
Body =
BlockBody
Position =
(50.0, 30.0, 0.0)
[BlockGraphic]
Texture =
data/block.png
Pivot =
center
[BlockBody]
Dynamic =
false
PartList =
BlockPartTemplate
[BlockPartTemplate]
Type =
box;
Friction =
0.0;
Restitution =
1.0;
Density =
1.0;
SelfFlags =
0x0001;
CheckMask =
0x0001;
Solid =
true;
特別需要注意的是,Orx的設計上常常會讓人感覺很多時候一個段的東西拆了幾個段,寫起來很麻煩,但是每個段都是可以復用的,比如此例中,所有的Block都共用一個Body。所以作者從長遠考慮才這樣做。
然后,再給Ball 一個速度。你就能夠看到物理的作用了。球從paddle反彈到block再反彈到paddle。帶角度。。。。。。。。。
碰撞檢測
打磚塊的游戲要求球碰到磚塊時磚塊消失的,這個需要做碰撞檢測,這在Orx中也是很簡單的,需要進行物理的Event響應,這是個新內容。
首先,初始化的時候,添加關注的事件。
orxEvent_AddHandler(orxEVENT_TYPE_PHYSICS, GameApp::EventHandler);
這個沒有什么好說的,別忘了就行。
然后,就是在注冊函數中物理的響應了,此例中是GameApp::EventHandler。
// Event handler
orxSTATUS orxFASTCALL GameApp::EventHandler(
const
orxEVENT *_pstEvent)
{
orxSTATUS eResult = orxSTATUS_SUCCESS;
if
(_pstEvent->eType == orxEVENT_TYPE_PHYSICS) {
if
( _pstEvent->eID == orxPHYSICS_EVENT_CONTACT_ADD ) {
/*
Gets colliding objects
*/
orxOBJECT *object_recipient = orxOBJECT(_pstEvent->hRecipient);
orxOBJECT *object_sender = orxOBJECT(_pstEvent->hSender);
string recipient_name(orxObject_GetName(object_recipient));
string sender_name(orxObject_GetName(object_sender));
if
(recipient_name ==
"Ball"
&& sender_name !=
"Paddle"
) {
orxObject_Delete(object_sender);
}
}
}
// Done!
return
orxSTATUS_SUCCESS;
}
有了代碼后,其實基本上意思都很明顯了,先判斷事件的類型,然后判斷事件的ID(其實相當于某類型事件中的子類型),這里判斷的是物理的contact_add,表示有碰撞(外國人喜歡說有接觸?)產生的時候。然后通過名字去判斷兩個物體是什么。這里沒有考慮效率,直接用名字來判斷了(事實上可以通過設定 userdate,然后通過ID判斷),再進一步,為了方面直接用std::string而沒有通過strcmp了。
判斷被推開的物體是球,而且還不是paddle推開的,那么就肯定是block了,此時用
orxObject_Delete
將其刪除,實現打磚塊的消除效果。
需要完善的部分
游戲其實基本成型了,剩下的,就是給游戲加個邊框,(這個都不需要我額外講方法了)不然球飛出去了,然后就是操作部分了,下一節再講。
原創文章作者保留版權 轉載請注明原作者 并給出鏈接
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
