write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie
雖然很早就想用做一個(gè)完整游戲來(lái)完成此教程,但是在做什么游戲的問(wèn)題上很糾結(jié),太大太好的游戲太費(fèi)精力,太小的游戲又不足以展示Orx的特點(diǎn),選來(lái)選去也沒(méi)有自己感覺(jué)最合適的,最后還是選擇打磚塊吧,此游戲雖然不能展示Orx的全部特點(diǎn),但是很好的展示了其內(nèi)嵌物理引擎的特點(diǎn)。因?yàn)镺rx內(nèi)嵌Box2D物理引擎,所以在游戲中使用物理,從來(lái)沒(méi)有這么方便過(guò),也許,哪天我該寫一篇用Cocos2D+Box2D的類似文章來(lái)做比較。
Orx 中的Object概述
在Orx中一個(gè)Object到底表示什么?簡(jiǎn)單的說(shuō),表示一切。一切有形的無(wú)形的,可見(jiàn)的不可見(jiàn)的東西。在Orx中,所有所有的概念全部歸結(jié)于 Object。所有其他的東西,都是Object的屬性。包括通常概念里面的sprite,animation等等,在Orx中還包括特效(fx),物理屬性等。在幾乎所有的2D游戲引擎中,幾乎都是是Sprite為基礎(chǔ)的,而在Orx中,是以O(shè)bject為基礎(chǔ)的。
顯示一個(gè) Object
在幾乎所有的2D游戲引擎中,幾乎都是是Sprite為基礎(chǔ)的,所以最基本的操作都是顯示一個(gè)Sprite,那么,換到Orx中,最基礎(chǔ)的那就是顯示一個(gè) Object了。
其實(shí),在原來(lái)《
站在巨人的肩膀上開(kāi)發(fā)游戲(2) -- Orx入門引導(dǎo)及Hello World
》中,我們已經(jīng)顯示過(guò)一個(gè) Object了,沒(méi)錯(cuò),那個(gè)Hello World的文字就是一個(gè)Object.........只不過(guò)其圖形是顯示文字而已。所以,我們創(chuàng)建Hello World的時(shí)候,調(diào)用的接口是
orxObject_CreateFromConfig
。
要將其換成顯示圖形,只需要改配置,將其顯示成一個(gè)圖形即可,因?yàn)槭亲龃虼u塊游戲,這里,我顯示一個(gè)球。(這里的資源全部來(lái)自于《
How To Create A Breakout Game with Box2D and Cocos2D Tutorial
》)順面可以將Orx版本的程序與Cocos2D + Box2D(另外一個(gè)我非常喜歡的組合)做比較。
原代碼的改動(dòng)僅出于代碼可讀性考慮,將HelloWorld改為Ball,Orx的特點(diǎn)之一,不改代碼,你甚至可以使用原來(lái)編譯好的Hello World程序(必須是教程1老的那個(gè),教程2新的那個(gè)我做了特殊處理),只需要將新的配置中的Ball改為HelloWorld即可。當(dāng)然,出于可讀性,這樣做不自然,但是我還是提及這樣做的可能性。
新添加配置如下:
[Ball]
Graphic =
BallGraphic
Position =
(0.0, 0.0, 0.0) ;球所在的位置
[BallGraphic]
Texture =
data/ball.png ;球圖形的png文件的位置
Pivot =
center
原來(lái)的代碼如下:
// 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;
}
然后,就能顯示出個(gè)球了。(顯示個(gè)球-_-!)
就這么一個(gè)Object顯示出來(lái)以后,就可以繼續(xù)自由發(fā)揮了,很多的想象空間。
比如Scale = XXX調(diào)整球的大小。
比如Speed = (xxx, xxx, xxx) 給球初始速度,
(上面的屬性都添加到
[Ball]
段)
按照上面的方法,按打磚塊游戲的特點(diǎn),添加磚塊及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;
}
代碼實(shí)在就是沒(méi)有太多好說(shuō)的了,在Orx中,永遠(yuǎn)是配置復(fù)雜,代碼簡(jiǎn)單。說(shuō)說(shuō)配置中的新東西,我在這里用
[Blocks]
ChildList =
Block1 # Block2 # Block3 # Block4
的形式+一行創(chuàng)建Blocks的代碼,來(lái)完成了4個(gè)磚塊的創(chuàng)建。這是Orx中使用子列表的一種方式。
效果如下:(我把窗口大小也改了)
是不是有那么一點(diǎn)意思了?
到目前為止,我們學(xué)到什么了?4行配置。。。。。。。。。。
且只有Graphic加
Texture算是新內(nèi)容。
只要這些,你通過(guò)position就可以完成你想要的任何圖形布局了。
當(dāng)然,其實(shí)遠(yuǎn)遠(yuǎn)不止這些,請(qǐng)參考Orx的WIKI獲取更多的信息:
物理的加入
好了,現(xiàn)在是添加真的游戲內(nèi)容的時(shí)候了。光是靜態(tài)圖形可做不了游戲。
在打磚塊的游戲中,很重要的就是球的碰撞,反彈,以及碰撞的檢測(cè)了。由于Orx中內(nèi)嵌了Box2D引擎,我們能夠很方便的使用,我多次提到是內(nèi)嵌,而不是外掛,不是如Cocos2D那種僅僅包含一個(gè)Box2D,然后需要你調(diào)用Box2D的API去完成的那種,事實(shí)上,你可以根本不知道Box2D是啥。(其實(shí)個(gè)人感覺(jué),了解Box2D的相關(guān)概念是必要的,不然怎么知道各個(gè)屬性應(yīng)該怎么配置啊)
首先,物理世界的加入:
[Physics]
DimensionRatio =
0.1
WorldLowerBound =
(-300.0, -300.0, 0.0)
WorldUpperBound =
(300.0, 300.0, 0.0)
這是必須的,似乎屬于Box2D為了優(yōu)化而添加的,Orx為了靈活,沒(méi)有自動(dòng)的去配置這些屬性,一般而言,將其設(shè)為包含整個(gè)游戲屏幕即可。(稍微大一點(diǎn)點(diǎn))配置的是一個(gè)矩形的左上角和右下角。(注意Orx的坐標(biāo)系啊)
然后,為各個(gè)物體添加物理屬性,最主要的是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的中添加了一個(gè)
Body =
BallBody
,然后所有的物理部分都寫在了BallBody和BallPartTemplate中。先說(shuō)明一下,之所以我把part叫template,而且Orx的作者添加了這樣一個(gè)新的段來(lái)表示物理部分,包括命名為part,是因?yàn)镺rx允許一個(gè)body有多個(gè)part組合成一個(gè)object的物理。這在某些時(shí)候也極為有用。比如希望有個(gè)組合圖形,一個(gè)part無(wú)法表示的時(shí)候。
至于各個(gè)物理的屬性的含義,推薦先去了解一下
Box2D 的各個(gè)定義
。要圖省事,看看
Orx的說(shuō)明
也行。
然后,如法炮制,基本的意思就有了。
[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的設(shè)計(jì)上常常會(huì)讓人感覺(jué)很多時(shí)候一個(gè)段的東西拆了幾個(gè)段,寫起來(lái)很麻煩,但是每個(gè)段都是可以復(fù)用的,比如此例中,所有的Block都共用一個(gè)Body。所以作者從長(zhǎng)遠(yuǎn)考慮才這樣做。
然后,再給Ball 一個(gè)速度。你就能夠看到物理的作用了。球從paddle反彈到block再反彈到paddle。帶角度。。。。。。。。。
碰撞檢測(cè)
打磚塊的游戲要求球碰到磚塊時(shí)磚塊消失的,這個(gè)需要做碰撞檢測(cè),這在Orx中也是很簡(jiǎn)單的,需要進(jìn)行物理的Event響應(yīng),這是個(gè)新內(nèi)容。
首先,初始化的時(shí)候,添加關(guān)注的事件。
orxEvent_AddHandler(orxEVENT_TYPE_PHYSICS, GameApp::EventHandler);
這個(gè)沒(méi)有什么好說(shuō)的,別忘了就行。
然后,就是在注冊(cè)函數(shù)中物理的響應(yīng)了,此例中是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;
}
有了代碼后,其實(shí)基本上意思都很明顯了,先判斷事件的類型,然后判斷事件的ID(其實(shí)相當(dāng)于某類型事件中的子類型),這里判斷的是物理的contact_add,表示有碰撞(外國(guó)人喜歡說(shuō)有接觸?)產(chǎn)生的時(shí)候。然后通過(guò)名字去判斷兩個(gè)物體是什么。這里沒(méi)有考慮效率,直接用名字來(lái)判斷了(事實(shí)上可以通過(guò)設(shè)定 userdate,然后通過(guò)ID判斷),再進(jìn)一步,為了方面直接用std::string而沒(méi)有通過(guò)strcmp了。
判斷被推開(kāi)的物體是球,而且還不是paddle推開(kāi)的,那么就肯定是block了,此時(shí)用
orxObject_Delete
將其刪除,實(shí)現(xiàn)打磚塊的消除效果。
需要完善的部分
游戲其實(shí)基本成型了,剩下的,就是給游戲加個(gè)邊框,(這個(gè)都不需要我額外講方法了)不然球飛出去了,然后就是操作部分了,下一節(jié)再講。
原創(chuàng)文章作者保留版權(quán) 轉(zhuǎn)載請(qǐng)注明原作者 并給出鏈接
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

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