Cocosbuilder使用教程
轉(zhuǎn)自:http://article.ityran.com/archives/2544
轉(zhuǎn)自:http://article.ityran.com/archives/2544
手把手教你使用CocosBuilder一次性導(dǎo)出Cocos2d-html5,Cocos2d-x和Cocos2d-iPhone的游戲資源文件。這個(gè)游戲90%的工作量是用工具完成。
CocosBuilder2.1 泰然下載地址 CocosDragon完整工程GitHub地址 在線Cocos2d-HTML5版本試玩地址 這篇教程將會(huì)展示如何使用?CocosBuilder和cocos2d-iphone制作游戲的動(dòng)作,地圖場(chǎng)景和界面。CocosBuilder?已經(jīng)被Zynga?使用在游戲Dream PetHouse?和?Zynga Slots開發(fā)中。目前,由于若干游戲使用CocosBuilder,Zynga?索性將其開源出來(lái)(MIT License)。未來(lái)必定有更多的游戲在開發(fā)中使用該工具。 這篇文章是建立在你很熟悉object-c以及cocos2d-iphone或者cocos2d-x的基礎(chǔ)上的。如果你希望學(xué)習(xí)cocos2d,泰然也有很多文章推薦給你。 在開始本文之前,確保你下載并安裝了CocosBuilder?的最新版(本教程基于2.1beta版本)并且升級(jí)cocos2d2.0或cocos2d-x的2.03版本以上。The Game
我們將創(chuàng)造游戲主角Cocos?Dragon。Cocos?Dragon有一對(duì)很小的翅膀因此他飛不高,所以我們需要讓他觸碰金幣來(lái)給他加速上升直到碰到炸彈為止。你可以到y(tǒng)outube看這個(gè)游戲的視屏:youtube本游戲可以在iOS模擬器上運(yùn)行,游戲通過(guò)觸摸來(lái)操作方向。假如你希望把這個(gè)游戲設(shè)計(jì)運(yùn)用到你的產(chǎn)品中,我推薦你用重力感應(yīng)來(lái)替換觸摸方式。
設(shè)置工程
建立新的xcode工程。工程名稱:CocosDragon。下載本教程需要用到的美術(shù)資源,解壓并加到工程中。 現(xiàn)在我們需要建立游戲相應(yīng)的CocosBuilder?工程。打開CocosBuilder?選擇File?->New Project。命名為CocosDragon?保存并把資源文件放到xcode的Resources?文件夾(CocosBuilder的資源在一個(gè)名為ccbResources的文件夾)打開theHelloCocosBuilder.ccb文件.我們不會(huì)使用HelloCocosBuilder?文件,所以你可以在CocosBuilder文件系統(tǒng)中干掉他。
創(chuàng)建動(dòng)畫類型的主界面
我們將開始制作Cocos Dragon所有的界面文件,然后將界面鏈接到相應(yīng)的代碼中。首先,我們創(chuàng)建一個(gè)主菜單。 在CocosBuilder打開的CocosDragon?工程中選擇File->New File。我們將讓主界面只支持iPhone,所以在resolutions settings(方案設(shè)置)中勾選iPhone?Portrait?,并確保root object type(根對(duì)象類型)為CCLayer?并勾選full screen?(全屏)。點(diǎn)擊創(chuàng)建,然后命名為“?MainMenuScene?”并且保存到Resources?文件夾。一個(gè)新的空文件MainMenuScene.ccb將在CocosBuilder中開啟。
主界面我們會(huì)包含一個(gè)漸變的背景,一個(gè)logo,一個(gè)開始游戲的按鈕,和幾片云彩的動(dòng)畫。首先,讓我們開始加入漸變的背景。在窗口頂部的工具欄點(diǎn)擊CCLayerGradient?按鈕。
我們希望漸變層(gradient layer)充滿整個(gè)屏幕。選擇這個(gè)層,設(shè)置填充(content size)大小單位為“%”并且設(shè)置寬高為100×100.
讓我們把顏色修改為其他值以遍更適合我們游戲的主色調(diào)。點(diǎn)擊開始顏色(start color)和完成顏色(?end color)以至RGB值為下圖顯示這樣。
繼續(xù)添加logo到主界面(?menu scene)。在左邊的工程視圖(project view)中,拖拽logo.png到canvas?區(qū)域。你添加的圖片就會(huì)像如下那樣顯示:
當(dāng)啟動(dòng)主選單場(chǎng)景時(shí)會(huì)有漂亮的動(dòng)畫,但是我們還需要在啟動(dòng)時(shí)增加logo的動(dòng)畫。首先,點(diǎn)擊canvas?區(qū)域下面的時(shí)間設(shè)置來(lái)指定動(dòng)畫的長(zhǎng)度。這里我們把動(dòng)畫出現(xiàn)的時(shí)間線設(shè)置為2秒。
現(xiàn)在,我們把logo視為一個(gè)精靈,并設(shè)置logo精靈的關(guān)鍵幀(keyframes?)。拖拽時(shí)間戳到動(dòng)畫完成的地方(我們這個(gè)工程就是之前設(shè)置的?00:02:00),并且確保logo已經(jīng)被選定。在動(dòng)畫菜單中選擇插入關(guān)鍵幀位置(Keyframe /Position),或者使用快捷鍵’P’.在時(shí)間線界面(timeline view),logo精靈會(huì)折疊并顯示剛才添加的關(guān)鍵幀。
一旦關(guān)鍵幀插入時(shí)間線的節(jié)點(diǎn)中,我們節(jié)點(diǎn)的位置既可以自動(dòng)添加新的關(guān)鍵幀。首先,移動(dòng)時(shí)間戳到原點(diǎn)(00:00:00的位置)。然后,拖拽logo到繪圖界面(?canvas area)的頂部可見區(qū)域(你可以在拖拽的時(shí)候按住shift按鈕以便對(duì)齊)。當(dāng)你正在做以上操作時(shí),一個(gè)新的關(guān)鍵幀就被自動(dòng)添加到時(shí)間線的原點(diǎn)處,并且我們?cè)趦蓚€(gè)關(guān)鍵幀中間生成平滑過(guò)渡的所有幀。
你可以點(diǎn)擊Play來(lái)測(cè)試一下這個(gè)動(dòng)畫。你也可以移動(dòng)時(shí)間戳來(lái)看看每個(gè)幀的位置。
這個(gè)動(dòng)畫我們完成的很漂亮并且每幀的過(guò)渡很平滑,但是讓我們?cè)偌狱c(diǎn)料。在關(guān)鍵幀之間右擊?插值線(譯者注:interpolation line,就是插入了過(guò)渡幀的地方)并且選擇彈出(Bounce Out)。
OK,我們讓logo被覆蓋了,但是我們依然需要一個(gè)啟動(dòng)游戲的按鈕。我們將用CCMenu?和CCMenuItemImage來(lái)實(shí)現(xiàn)這個(gè)功能。那么,開始添加菜單功能,在工具欄中點(diǎn)擊CCMenu按鈕。如下圖:
一個(gè)CCMenu?將會(huì)添加到你的文件中。CCMenu?保持選中狀態(tài),在工具欄點(diǎn)擊CCMenuItemImage?按鈕(在CCMenu按鈕右邊)。CCMenuItemImage?會(huì)在可是換編輯區(qū)域左下角顯示一個(gè)占位符圖像。
拖動(dòng)這個(gè)圖片到屏幕中間,也可以使用Cmd+方向鍵或者 Cmd+shift+方向鍵來(lái)精準(zhǔn)拖動(dòng),檢視器(?inspector)中輸入需要的值。選中CCMenuItemImage?,選擇你希望菜單顯示的其他圖片樣式。通常情況,未按下時(shí)我們使用圖片名稱“play-button.png”,按下時(shí)我們使用“?play-button-down.png”。
我們現(xiàn)在又一個(gè)帶logo和play?按鈕的選擇菜單場(chǎng)景,但是這還是感覺(jué)有點(diǎn)空蕩蕩的。所以我們加入一些云彩來(lái)充實(shí)一下。在工程界面,拖拽一些云 彩到可視化區(qū)域。你可以拖拽圖片的邊角來(lái)改變?cè)撇实拇笮 R淖冊(cè)撇实恼谏w(z-order)可以在時(shí)間線區(qū)域?qū)⑾鄳?yīng)的時(shí)間線拖到上面或者下面,當(dāng)然也可 以在對(duì)象選項(xiàng)中(Object?menu)選擇Arrange / Bring放到上層,選擇Arrange / Send放到下層。
現(xiàn)在讓我們添加云彩的介紹動(dòng)畫。這就像之前l(fā)ogo精靈那樣做就好。把時(shí)間戳移動(dòng)到動(dòng)畫的末尾。給每個(gè)云彩和play按鈕添加一個(gè)關(guān)鍵幀。你可以選 中每個(gè)云彩然后點(diǎn)擊快捷鍵‘p’。當(dāng)關(guān)鍵幀已經(jīng)被添加到所有對(duì)象的動(dòng)畫末尾后,把時(shí)間戳移動(dòng)到動(dòng)畫開頭。現(xiàn)在拖拽每個(gè)云彩,讓底部
點(diǎn)擊‘Play’來(lái)測(cè)試動(dòng)畫。我們現(xiàn)在有一個(gè)很漂亮的主菜單介紹動(dòng)畫。當(dāng)動(dòng)畫播放完畢后,整個(gè)場(chǎng)景就是完全禁止的。這不是很好,所以后面我們還會(huì)完善。
CocosBuilder提供了多個(gè)時(shí)間線。在文件中,多個(gè)時(shí)間線可以連續(xù)或者不連續(xù)播放,也可以通過(guò)代碼控制回放。兩個(gè)不同動(dòng)畫的時(shí)間線可以實(shí)現(xiàn)平滑過(guò)渡。我們這個(gè)工程會(huì)實(shí)現(xiàn)多個(gè)時(shí)間線,當(dāng)介紹動(dòng)畫的時(shí)間線播放完成后,會(huì)循環(huán)播放另一個(gè)動(dòng)畫。
在動(dòng)畫菜單選擇編輯時(shí)間線(Edit Timelines)。在彈出框中,先將默認(rèn)的時(shí)間線重命名為Intro。然后點(diǎn)擊plus-sign添加一條時(shí)間線并命名為L(zhǎng)oop,點(diǎn)擊完成。
我們選擇要編輯的時(shí)間線,點(diǎn)擊drop-down按鈕(圖上已經(jīng)標(biāo)出),選中Timelines->Loop。
現(xiàn)在我們有一條未添加關(guān)鍵幀的時(shí)間線。這條時(shí)間線默認(rèn)是10秒鐘,我們的工程剛好就要這么長(zhǎng)。為了方便看出完成后的長(zhǎng)度,你可以拖動(dòng)比例條(scale slider)到左邊。
雖然只是一個(gè)很小的動(dòng)畫,但可以給場(chǎng)景帶來(lái)生機(jī)。選擇一片云彩。將時(shí)間戳拖到起點(diǎn),點(diǎn)擊快捷鍵’s'。這將會(huì)給比例屬性添加一個(gè)關(guān)鍵幀。現(xiàn)在把時(shí)間 戳拖動(dòng)到時(shí)間線末尾并再次點(diǎn)擊快捷鍵‘s’。這將會(huì)在動(dòng)畫末尾添加一個(gè)關(guān)鍵幀。注意,這條線表示插入的view將會(huì)輕微淡出。這是因?yàn)閮蓚€(gè)關(guān)鍵幀是完全一 樣的,所以沒(méi)有動(dòng)畫產(chǎn)生。現(xiàn)在這個(gè)情況就已經(jīng)不錯(cuò)了,因?yàn)槲覀兿M麆?dòng)畫的首尾相同,以便重復(fù)播放。
按住option鍵點(diǎn)擊兩個(gè)關(guān)鍵幀中間,就在時(shí)間線的開頭和結(jié)尾之間添加一個(gè)新的關(guān)鍵幀。點(diǎn)擊這個(gè)新建的關(guān)鍵幀讓它出于選中狀態(tài),通過(guò)調(diào)整比例值,或者拖動(dòng)云彩,讓云彩稍微變大一點(diǎn)。
回放動(dòng)畫,你可以看到一片云彩慢慢變大,然后再變回原始大小。讓我們給每片云彩做相同的操作。點(diǎn)擊所有的關(guān)鍵幀讓選擇框包含他們。你也可以用shift來(lái)選中。選中后,在Edit菜單選擇 復(fù)制。把時(shí)間戳移動(dòng)到時(shí)間線原點(diǎn),選擇另一片云彩點(diǎn)擊粘貼。并重復(fù)在所有云彩中操作(并沒(méi)有添加關(guān)鍵幀)。
再次回放動(dòng)畫。你可以看到所有的云彩都按比例做放大縮小動(dòng)作了,但是他們是在同時(shí)放大縮小,這很古怪,不是嗎?點(diǎn)擊每片云彩,延伸時(shí)間線,并移動(dòng)中間那個(gè)關(guān)鍵幀的位置。這樣就會(huì)讓云彩在不同時(shí)間播放動(dòng)畫了。多試幾次你就會(huì)有經(jīng)驗(yàn)調(diào)整到合適的長(zhǎng)度了。
最后,我們要讓動(dòng)畫在我們需要的時(shí)候自動(dòng)循環(huán),就要用到鏈?zhǔn)綍r(shí)間線功能(chain timeline?)。點(diǎn)擊時(shí)間線編輯器左下角的文本,這里顯示沒(méi)有鏈?zhǔn)綍r(shí)間線。彈出框中點(diǎn)擊 循環(huán)(loop)。這就會(huì)讓動(dòng)畫自動(dòng)循環(huán)了。
現(xiàn)在回到介紹動(dòng)畫的時(shí)間線(點(diǎn)擊時(shí)間線drop-down菜單,選擇Timelines -> Intro)。在Intro右邊完成的地方鏈接?Loop時(shí)間線。當(dāng)我們用代碼調(diào)用這個(gè)場(chǎng)景時(shí),會(huì)自動(dòng)播放Intro動(dòng)畫,Intro完成后回循環(huán)播放Loop動(dòng)畫。
主菜單的大部分已經(jīng)完成,我們剩下的僅僅是在代碼中調(diào)用這個(gè)界面。要調(diào)用這個(gè)場(chǎng)景,我們要給根節(jié)點(diǎn)設(shè)置一個(gè)定制類。選擇根節(jié)點(diǎn)(在文件document的CCLayer中)。設(shè)置類名為“MainMenuScene”。我們會(huì)在稍后在代碼中創(chuàng)建MainMenuScene。
選擇Play按鈕。進(jìn)入CCMenuItem下的pressedPlay:進(jìn)入選擇器的輸入框,選擇目標(biāo)“Document root”。當(dāng)我們點(diǎn)擊按鈕pressedPlay:文件根節(jié)點(diǎn)方法(MainMenuScene)就會(huì)被調(diào)用。
游戲場(chǎng)景
我們使用游戲場(chǎng)景來(lái)載入在實(shí)際游戲中需要的所有東西。同時(shí)它也用來(lái)顯示分?jǐn)?shù)。在file菜單中選擇New File?并選擇和你MainMenuScene中選擇的相同的選項(xiàng)(CCLayer, full screen, iPhone portrait),命名文件為GameScene并保存在文件夾。
對(duì)于這個(gè)游戲來(lái)說(shuō),我們會(huì)使用和菜單場(chǎng)景一樣的背景梯度。或是再創(chuàng)建一遍,或是通過(guò)雙擊項(xiàng)目視圖的MainMenuScene,選擇CCLayerGradient,復(fù)制黏貼到你的新文件處。
點(diǎn)擊工具欄上的CCLayer圖標(biāo)來(lái)給場(chǎng)景加一個(gè)層。稍后在代碼中我們會(huì)使用這個(gè)空的層來(lái)加載一個(gè)關(guān)卡。
層添加后,我們添加一個(gè)label用來(lái)顯示當(dāng)前游戲的分?jǐn)?shù)。點(diǎn)擊工具欄上的CCLabelTTF標(biāo)簽。
如圖所示,把位置設(shè)成(160,40),字體設(shè)置成o?System Fonts / MarkerFelt-Wide,字號(hào)大小24,尺寸設(shè)成100*40,校準(zhǔn)設(shè)成center,最后把文字設(shè)成“0”
這個(gè)游戲場(chǎng)景已經(jīng)差不多完工了,唯一還差的就是和代碼的連接。選擇根節(jié)點(diǎn)并且設(shè)置自定義類為GameScene。然后選擇文本標(biāo)簽,我們將要指派這個(gè)標(biāo)簽作為根節(jié)點(diǎn)類的一個(gè)成員變量。將左側(cè)的下拉菜單中選擇為Doc root var,并且設(shè)置那個(gè)變量的名字為scoreLabel。
我們也需要連接剛才創(chuàng)建的那個(gè)空層到代碼。處理步驟同上并將變量明設(shè)為levelLayer。
現(xiàn)在我們已經(jīng)完成這個(gè)游戲場(chǎng)景啦。讓我們繼續(xù)創(chuàng)建一些游戲?qū)ο蟆?/p>
增加游戲物體
我們這個(gè)游戲會(huì)用到4種游戲物體。游戲的主角:龍,以及錢幣,炸彈,和爆炸效果。所有游戲物體都是我們稍后創(chuàng)建的GameObject類的子類。GameObject類是CCNode的一個(gè)子類。因此,CocosBuilder創(chuàng)建的游戲中的所有對(duì)象都繼承自CCNode。(當(dāng)然還有可能作為GameObject的插件程序存在,但是在本游戲中,我們并需要使用)。
龍
讓我們開始創(chuàng)建游戲中最復(fù)雜的物體—龍。在File菜單中選取New File,創(chuàng)建一個(gè)新文件。選擇根節(jié)點(diǎn)對(duì)象為CCNode,反選全屏選項(xiàng)(full screen),選擇分辨率選項(xiàng)為iphone。
選擇根節(jié)點(diǎn)并設(shè)置自定義類為Dragon。
龍由幾個(gè)不同的移動(dòng)部件組成:身體和2個(gè)翅膀。首先我們先加入翅膀這樣他們就會(huì)出現(xiàn)在身體的后面。在項(xiàng)目視圖拖動(dòng)gameobjects.plist/dragon-wing.png?到畫布區(qū)域。設(shè)置翅膀的位置為(-8,4),另一個(gè)錨點(diǎn)設(shè)為(0.84,0.094).
然后,增加身體部分。拖動(dòng)gameobjects.plist/dragon-body.png到畫布區(qū)域。設(shè)置身體的位置為(0,0)。你的文件看起來(lái)就會(huì)是這樣:
我們將龍的單個(gè)翅膀做動(dòng)畫,然后復(fù)制翅膀并翻轉(zhuǎn)成一對(duì)做動(dòng)畫的翅膀。首先,設(shè)置時(shí)間軸長(zhǎng)度為1秒。然后,選擇翅膀,將時(shí) 間軸標(biāo)記(timeline)移到開始處并按R鍵來(lái)增加一幀,以做翻轉(zhuǎn)。將時(shí)間軸(timeline)標(biāo)記移動(dòng)到結(jié)束處,再增加一幀翻轉(zhuǎn)。現(xiàn)在移動(dòng)到中部 (00:00:15)。朝下旋轉(zhuǎn)翅膀—-你可以通過(guò)按住option鍵,并拖曳其中一個(gè)選擇選擇點(diǎn)來(lái)快捷旋轉(zhuǎn)它。旋轉(zhuǎn)這個(gè)翅膀差不多80度左右。
我們現(xiàn)在有了撲騰的翅膀啦,但是通過(guò)增加Bounce Out緩沖,我們可以讓它顯示的更加自然。在第一幀和中間幀之間右鍵,選擇Bounce Out.。在中間那幀和最后一幀也做同樣的設(shè)置。
現(xiàn)在來(lái)創(chuàng)建另外一只翅膀。首先確保沒(méi)有幀被選中,然后選擇翅膀。在edit菜單中選擇Copy,并Paste.第二個(gè)翅膀就被復(fù)制到龍的身體前面了,因此我們需要使用Object菜單中的Arrange /Send Backward選項(xiàng)。請(qǐng) 確保新的翅膀在檢查器中FilpX選項(xiàng)有被選中。這只會(huì)翻轉(zhuǎn)圖像,我們同意需要設(shè)置它的位置和錨點(diǎn),設(shè)置位置為(8,4),錨點(diǎn) (0.16,0.094)。這個(gè)翅膀的動(dòng)畫現(xiàn)在看起來(lái)不錯(cuò)了,但是選擇的方向是錯(cuò)的。雙擊中間的那一幀來(lái)鎖定它。你可以改變檢查器(inspector) 中的旋轉(zhuǎn)角度(大概80度左右)。繼續(xù)播放動(dòng)畫,這時(shí)候,龍的兩只翅膀應(yīng)該都正常了。
在游戲中,我們的小龍會(huì)在碰到炸彈的時(shí)候停止撲騰它的翅膀。當(dāng)撞到炸彈的時(shí)候,我們會(huì)播放另一個(gè)剪短的動(dòng)畫,然后再撲騰翅膀。因此我們需要2個(gè)時(shí)間軸。選擇Animation?菜單的Choose?Edit Timelines…。重命名當(dāng)前的時(shí)間軸為Flying,增加一個(gè)新的時(shí)間軸為Hit,然后點(diǎn)擊Done
我們希望飛行的時(shí)間軸循環(huán)播放,所有點(diǎn)擊No chained timeline并選擇Flying。然后切換到新創(chuàng)建的Hit時(shí)間軸。設(shè)置它的長(zhǎng)度為2秒并和Flying連接起來(lái)。當(dāng)龍被擊中時(shí)候,我們播放hit動(dòng)畫,播放完成后它自動(dòng)繼續(xù)Flying動(dòng)畫。
剩下還有要做的就是創(chuàng)建一個(gè)龍被擊中的動(dòng)畫。移動(dòng)時(shí)間軸的標(biāo)記到末尾,選擇每個(gè)翅膀并按R來(lái)增加旋轉(zhuǎn)動(dòng)畫。現(xiàn)在移動(dòng)標(biāo)記到開頭。將每個(gè)翅膀旋轉(zhuǎn)向下,我分別設(shè)置了-123和123的值。為每個(gè)翅膀增加一個(gè)Bounce Out屬性。
選擇龍的身體部分,移動(dòng)時(shí)間軸標(biāo)記到00:00:15.處。按F來(lái)增加一幀。現(xiàn)在,移動(dòng)標(biāo)記到開頭處并按F增加一個(gè)精靈幀。在檢查器(inspector)中,設(shè)置精靈框?yàn)閒rame?togameobjects.plist/dragon-body-hit.png。點(diǎn)擊play按鈕來(lái)試試hit動(dòng)畫怎么樣。
Bomb
炸彈
在街機(jī)游戲中怎么可能會(huì)少了壞人?我們需要一些很酷的炸彈~創(chuàng)建一個(gè)新文件就像dragon文件一樣(選項(xiàng)也一樣)。命名文件為Bomb并保存。選擇根節(jié)點(diǎn)并設(shè)置自定義類為Bomb。
我們現(xiàn)在要為我們的炸彈增加一些旋轉(zhuǎn)的釘子。設(shè)置時(shí)間軸長(zhǎng)度為2s。拖曳gameobjects.plist-bomb-spikes.png到畫布處并設(shè)置位置為(0,0),同樣的拖曳thegameobjects.plist/bomb-body.png。炸彈身體會(huì)在尖刺的上方。
為了讓炸彈看起來(lái)更邪惡一點(diǎn),我們需要讓釘子旋轉(zhuǎn)。選擇釘子精靈并移動(dòng)時(shí)間軸標(biāo)記至初始部分。按R來(lái)增加一幀旋轉(zhuǎn)的關(guān)鍵幀。通過(guò)移動(dòng)時(shí)間軸標(biāo)記到末尾增加一個(gè)關(guān)鍵幀(按R鍵)并設(shè)置精靈的旋轉(zhuǎn)角度是360度。播放動(dòng)畫,我們可以看到釘子繞著身體旋轉(zhuǎn)了。
最后,請(qǐng)確保時(shí)間軸自動(dòng)的循環(huán)播放,你可以動(dòng)過(guò)點(diǎn)擊No chained timeline?text?并選擇Default的時(shí)間軸。
Coin
硬幣
在我們的游戲中我們會(huì)看到2種硬幣,普通硬幣和結(jié)束硬幣。吃了普通硬盤會(huì)給與我們的龍一個(gè)短暫的加速,吃了結(jié)束硬幣會(huì)結(jié)束當(dāng)前關(guān)卡。我們可以使用相同的類對(duì)于這2種硬幣,但是在其中加一個(gè)額外的屬性以方便我們?cè)诖a中區(qū)分他們。
用和dragon,bomb文件一樣的設(shè)置創(chuàng)建一個(gè)新文件。命名為Coin,設(shè)置自定義類為Coin。
拖曳gameobjects.plist/coin01.png到畫布區(qū)并設(shè)置位置為(0,0)。現(xiàn)在我們想要增加一幀基于硬幣的動(dòng)畫,設(shè)置時(shí)間軸的長(zhǎng)度為00:01:06.確保時(shí)間軸標(biāo)記在最前面而且硬幣精靈被選中。現(xiàn)在選擇項(xiàng)目視圖中的coin01.png到coin18.png。
選擇Animation?菜單中的Create Frames from Selected Resources按鈕。你將為硬幣精靈添加一系列的關(guān)鍵幀。動(dòng)畫起了作用,但是好像稍微太快了點(diǎn)。拖動(dòng)選擇框包圍他們來(lái)選擇所有的關(guān)鍵幀,然后,選擇Animation?菜單中的Stretch Selected Keyframes?按鈕。設(shè)置拉伸率(stretch)為2.0并點(diǎn)擊Done。這時(shí)關(guān)鍵幀時(shí)間被隔開,動(dòng)畫看起來(lái)就更慢了。
對(duì)于炸彈,通過(guò)設(shè)置默認(rèn)的時(shí)間軸,完成這個(gè)文件,并保存。
現(xiàn)在我們開始創(chuàng)建“結(jié)束硬幣”。打開Finder,復(fù)制Coin.ccb文件,并重命名為EndCoin.ccb。切回到CocosBuilder,雙擊項(xiàng)目視圖來(lái)新建一個(gè)文件。為了區(qū)別這2種硬幣,我們需要在根節(jié)點(diǎn)增加一個(gè)自定義的屬性。選擇根節(jié)點(diǎn)并點(diǎn)擊檢查器中的Edit Custom Properties。創(chuàng)建一個(gè)新的屬性,命名為isEndCoin,設(shè)置種類為Bool并設(shè)置值為1.點(diǎn)擊Done、
當(dāng)文件在我們的app中載入的時(shí)候,這個(gè)自定義屬性就會(huì)被設(shè)置進(jìn)自定義的類里。為了使這個(gè)旋轉(zhuǎn)的硬幣視覺(jué)上有別于普通的硬幣。選擇硬幣,并點(diǎn)擊color well來(lái)彈出顏色選取器,設(shè)置如下所示的顏色,這樣,我們就完成了2個(gè)不同的硬幣。
Explosion
爆炸
當(dāng)炸彈爆炸的時(shí)候,我們需要一些花哨的爆炸效果。我們可以使用粒子系統(tǒng)。每一個(gè)爆炸由2個(gè)粒子系統(tǒng)構(gòu)成。
首先創(chuàng)建一個(gè)新文件,設(shè)置都同前面創(chuàng)建龍、炸彈和硬幣的一樣并命名文件為Explosion。設(shè)置時(shí)間軸長(zhǎng)度為2秒,并定義根節(jié)點(diǎn)的自定義類名為Explosion。點(diǎn)擊工具欄的粒子系統(tǒng)的圖標(biāo)2次,來(lái)增加2個(gè)粒子系統(tǒng)的文件。
兩個(gè)粒子系統(tǒng)的參數(shù)設(shè)置如下圖所示。如果想看一下效果,你可以點(diǎn)擊檢查器中的Start Particles按鈕。
Creating a Level
創(chuàng)建一個(gè)關(guān)卡
我們完成了我們所有的游戲物體。唯一還沒(méi)做的界面就是關(guān)卡地圖了。創(chuàng)建一個(gè)新文件,請(qǐng)確保根節(jié)點(diǎn)中CCLayer和full screen的選項(xiàng)被選擇,選擇iPhone Portrait的分辨率,但是設(shè)置高度為4096.
將其保存為L(zhǎng)evel文件。設(shè)置根節(jié)點(diǎn)的自定義類名為L(zhǎng)evel。我們現(xiàn)在有一個(gè)很大的文件來(lái)放置我們這些游戲物體。首先先增加龍吧。將項(xiàng)目視圖中的Dragon.ccb拖曳到畫布區(qū)域。選擇龍并設(shè)置位置為(160,40),如果你移動(dòng)了龍,你可能需要滾動(dòng)畫布區(qū)域才能看到龍。我們需要向下滾動(dòng)可視化編輯器,以便你在移動(dòng)進(jìn)入前能看到我們添加的龍。我們希望能夠簡(jiǎn)便地在代碼中加入龍,所以在下拉菜單總的代碼連接選項(xiàng)(Code Connections)中選擇Doc root var。
現(xiàn)在,從項(xiàng)目視圖中拖曳并放置更多游戲物體。在我這種情況下,第一關(guān)看起來(lái)像這樣:
在關(guān)卡的頂部放置一個(gè)“結(jié)束硬幣”。當(dāng)龍接觸到“接觸硬幣”的時(shí)候,關(guān)卡結(jié)束。當(dāng)你很高興的布局你的關(guān)卡的時(shí)候,請(qǐng)確保所有打開的文件要保存。現(xiàn)在,選擇File菜單中的Publish按鈕。這將會(huì)把你的文件打包成一個(gè)非常緊湊的二進(jìn)制格式文件。
游戲編碼
現(xiàn)在我們已經(jīng)為游戲創(chuàng)建好了所有接口文件,下一步開始編碼。
用Xcode打開項(xiàng)目,右鍵單擊Resources文件夾并選擇Add Files to “CocosDragon”…….確保“Create groups for any added folders”單選框被選中,并且“CocosDragon?target”也被選中。將所有的圖片文件添加到資源目錄下,包括plist文件 (sprite sheets)和所有ccbi文件。你不必添加以ccb為擴(kuò)展名的文件進(jìn)來(lái),因?yàn)樗麄冎辉贑ocosBuilder下使用。
下一步,我們要添加CCBReader到項(xiàng)目下。CCBReader在示例代碼的文件夾下。將他添加到“你項(xiàng)目 /cocos2d-iphone”。將CCBReader文件夾添加到你項(xiàng)目之后,確認(rèn)Create groups for any added folders被選中,并且Copy items into destination group’s folder被選中。
Xcode下,打開Prefix.pch文件,它在Supporting Files組下。引入頭文件的代碼如下:
#ifdef __OBJC__ #import #import #import “cocos2d.h” #endif
MainMenuScene
我們現(xiàn)在開始編碼。讓我們一起創(chuàng)建一個(gè)主菜單(main menu)!選擇File菜單下的New/File。選擇Objective-C class,命名該類為MainMenuScene并設(shè)定該類為CCLayer的子類。
在MainMenuScene.m的最上部import?CCBReader.h。我們也將實(shí)現(xiàn)play按鈕的回調(diào)函數(shù),這個(gè)play按鈕是我們?cè)赾cb文件中加入的。在實(shí)現(xiàn)文件中(*.m)中加入如下代碼:
- (void) pressedPlay:(id)sender
{
?// Load the game scene
?CCScene* gameScene = [CCBReader sceneWithNodeGraphFromFile:@"GameScene.ccbi"];
?// Go to the game scene
?[[CCDirector sharedDirector] replaceScene:gameScene];
}
當(dāng)我們按下play按鈕,我們將第一次通過(guò)ccbi文件加載游戲場(chǎng)景。然后通知CCDirector去用游戲場(chǎng)景 replace掉當(dāng)前的場(chǎng)景。這部分的代碼我們需要寫到MainMenuScene里,而且需要在游戲開始時(shí)候加載。打開AppDelegate.m文 件,引入CCBReader.h,然后用下面的代碼替換既存的引入初始場(chǎng)景的代碼:
// Load the main menu scene from the ccbi-file
CCScene* mainScene = [CCBReader sceneWithNodeGraphFromFile:@"MainMenuScene.ccbi"];
// Then add the scene to the stack. The director will run it when it automatically when the view is displayed.
[director_ pushScene: mainScene];
然后,還是在AppDelegate.m文件,用如下代碼替換shouldAutorotateToInterfaceOrientation:方法:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
?return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
這將確保我們的游戲以豎屏模式運(yùn)行。你可以在github上找到源文件:
MainMenuScene.m
MainMenuScene.h
AppDelegate.m
GameScene
當(dāng)我們按下play按鈕之后,GameScene.ccbi文件將會(huì)被加載,并創(chuàng)建GameScene的實(shí)例。現(xiàn)在我們需要?jiǎng)?chuàng)建GameScene類。創(chuàng)建一個(gè)新類命名為GameScene,讓其繼承自CCLayer。
在CocosBuilder里,我們添加了兩個(gè)成員變量(levelLayer和scoreLabel)。我們需要添加它們到文件中去。并且也需要加載等級(jí)(Level)以及動(dòng)態(tài)的記錄當(dāng)前的分?jǐn)?shù)。在GameScene.h添加前面提到的兩個(gè)成員變量:
@interface GameScene : CCLayer
{
?CCLayer* levelLayer;
?CCLabelTTF* scoreLabel;
?CCNode* level;
?int score;
}
為了從別的類里更好的管理分?jǐn)?shù),我們將在GameScene類里增加一個(gè)屬性。我們也將增加方法去管理游戲結(jié)束以及升級(jí)的情況。
@property (nonatomic,assign) int score;
+ (GameScene*) sharedScene;
- (void) handleGameOver;
- (void) handleLevelComplete;
@end
下面我們來(lái)實(shí)現(xiàn)GameScene類的方法。打開GameScene.m。在頭部importCCBReader.h。在開始實(shí)現(xiàn)該類之前,先定義一個(gè)靜態(tài)變量以方便共享該類的實(shí)例。
static?GameScene* sharedScene;
在該類的類方法中返回這個(gè)共享實(shí)例。
+ (GameScene*) sharedScene
{
?return sharedScene;
}
我也需要去synthesize這個(gè)分?jǐn)?shù)屬性。
@synthesize score;
當(dāng)一個(gè)ccbi文件被加載的時(shí)候,CCBReader將會(huì)調(diào)用創(chuàng)建每個(gè)節(jié)點(diǎn)的方法didLoadFromCCB。通過(guò)實(shí)現(xiàn)該方法,你將在文件加載完畢的時(shí)候收到一個(gè)回調(diào)函數(shù)。我們將會(huì)利用回調(diào)信息去設(shè)置當(dāng)前場(chǎng)景以及加載等級(jí)。
- (void) didLoadFromCCB
{
?// Save a reference to the currently used instance of GameScene
?sharedScene = self;
?self.score = 0;
?// Load the level
?level = [CCBReader nodeGraphFromFile:@"Level.ccbi"];
?// And add it to the game scene
?[levelLayer addChild:level];
}
這部分代碼加載Level.ccbi文件并且將其作為一個(gè)子節(jié)點(diǎn)加到我們?cè)贑ocosBuilder里創(chuàng)建的levelLayer上。在真實(shí)的游戲當(dāng)中我們可能會(huì)有不止一個(gè)的等級(jí)文件,并且對(duì)應(yīng)玩家在游戲中的進(jìn)度選擇不同的文件。
當(dāng)分?jǐn)?shù)屬性改變時(shí),我們希望更新label上分?jǐn)?shù)的顯示。我們通過(guò)setScore:方法來(lái)實(shí)現(xiàn)。記住我們已經(jīng)在CocosBuilder定義了scoreLabel。
- (void) setScore:(int)s
{
?score = s;
?[scoreLabel setString:[NSString stringWithFormat:@"%d",s]];
}
離開GameScene之前的最后一步是為控制游戲結(jié)束以及升級(jí)編碼。在實(shí)際游戲中你可能做更多的事情在這些方法中,但是在該例子中,我們只是簡(jiǎn)單的返回主菜單場(chǎng)景。
- (void) handleGameOver
{
?[[CCDirector sharedDirector] replaceScene:[CCBReader sceneWithNodeGraphFromFile:@"MainMenuScene.ccbi"]];
}
- (void) handleLevelComplete
{
?[[CCDirector sharedDirector] replaceScene:[CCBReader sceneWithNodeGraphFromFile:@"MainMenuScene.ccbi"]];
}
你可以在github找到源碼
?GameScene.m
?GameScene.h
GameObject
GameObject是一個(gè)抽象類,它是所有游戲?qū)ο蟮母割悺K屛覀兛梢缘韧瑢?duì)待所有的游戲?qū)ο蟆?chuàng)建一個(gè)CCNode的子類,命名為GameObject。這個(gè)類包含一些基礎(chǔ)屬性的設(shè)置以及一些基礎(chǔ)的方法,以便我們?cè)谟螒虍?dāng)中控制游戲?qū)ο蟆H绻覀兿胍瞥粋€(gè)對(duì)象那么可以設(shè)置isScheduledForRemove屬性。這個(gè)更新方法會(huì)在每個(gè)框架更新游戲?qū)ο鬆顟B(tài)的時(shí)候調(diào)用一次。我們將在檢測(cè)沖突的時(shí)候(在我們的游戲當(dāng)中每一個(gè)游戲?qū)ο蠖家暈閳A形)使用radius屬性。最后,如果兩個(gè)游戲?qū)ο蟀l(fā)生碰撞,兩個(gè)發(fā)生碰撞的游戲?qū)ο蟮膆andleCollisionWith:方法將被調(diào)用。下面就是頭文件的定義代碼:
@interface GameObject : CCNode
{
?BOOL isScheduledForRemove;
}
@property (nonatomic,assign) BOOL isScheduledForRemove;
@property (nonatomic,readonly) float radius;
- (void) update;
- (void) handleCollisionWith:(GameObject*)gameObject;
@end
這個(gè).m文件只是實(shí)現(xiàn)了一個(gè)空方法,因?yàn)樗且粋€(gè)抽象類。
@implementation GameObject
@synthesize isScheduledForRemove;
// Update is called for every game object once every frame
- (void) update
{}
// If this game object has collided with another game object this method is called
- (void) handleCollisionWith:(GameObject *)gameObject
{}
// Returns the radius of this game object
- (float) radius
{?????return 0;
}
@end
源碼參見以下文件鏈接:
GameObject.m
GameObject.h
Dragon
龍是我們游戲中最復(fù)雜的游戲?qū)ο蟆K刂浦婕覍⒁刂频倪@個(gè)角色的行為,同時(shí)這也是游戲的主要行為。創(chuàng)建一個(gè)GameObject的子類命名為Dragon。
為了控制龍的運(yùn)動(dòng),我們需要兩個(gè)變量,縱向速度ySpeed,以及橫向目標(biāo)xTarget。xTarget將會(huì)在點(diǎn)擊iPhone上的打擊目標(biāo)的時(shí)候被設(shè)置。之后變量將會(huì)被外部類設(shè)定,我們將會(huì)將他作為一個(gè)屬性。下面是我們需要添加的頭文件:
@interface Dragon : GameObject
{
?float ySpeed;
?float xTarget;
}
@property (nonatomic,assign) float xTarget;
@end
.m文件將會(huì)更加有趣。首先,我們會(huì)整合一些其他的類進(jìn)來(lái),我們來(lái)引入他們。(我們將會(huì)在完成Dragon類之后,編寫Coin和Bomb類)
#import “Dragon.h”
#import “Coin.h”
#import “Bomb.h”
#import “GameScene.h”
#import “CCBAnimationManager.h”
下面,我們來(lái)定義幾個(gè)常量來(lái)方便對(duì)龍的行為的控制。使用常量是一個(gè)非常不錯(cuò)的選擇,因?yàn)檫@樣很方便我們?nèi)母泄偕峡刂朴螒颉?/p>
#define kCJStartSpeed 8
#define kCJCoinSpeed 8
#define kCJStartTarget 160
#define kCJTargetFilterFactor 0.05
#define kCJSlowDownFactor 0.995
#define kCJGravitySpeed 0.1
#define kCJGameOverSpeed -10
#define kCJDeltaToRotationFactor?5
實(shí)現(xiàn)Dragon類的第一步,我們需要synthesize屬性xTarget。
@synthesize xTarget;
然后來(lái)到init方法,在這里我們將初始化我們的成員變量。xTarget的初始值為160,位于屏幕中心。
- (id) init
{
?self = [super init];
?if (!self) return NULL;
?xTarget = kCJStartTarget;
?ySpeed = kCJStartSpeed;
?return self;
}
我們將使用update方法讓龍?jiān)谄聊簧掀交囊苿?dòng)。在每個(gè)frame下,update方法會(huì)被調(diào)用一次。我們將利用一 個(gè)計(jì)算原始點(diǎn)和目標(biāo)點(diǎn)之間距離的過(guò)濾器方法來(lái)獲得一個(gè)新的X坐標(biāo)。我所說(shuō)的目標(biāo)點(diǎn)就是玩家在屏幕上觸摸的點(diǎn)。Y坐標(biāo)則是在原始坐標(biāo)的基礎(chǔ)上增加現(xiàn)有速度來(lái) 計(jì)算得出的。之后我們更新速度,我們不但可以通過(guò)增加常量的方式加快速度,也可以利用參數(shù)減慢速度(這將防止龍的攻擊速度過(guò)快)。我們同時(shí)依靠水平速度翹 起龍的一側(cè)。如果縱向速度向下過(guò)快,那么游戲結(jié)束。
- (void) update
{
?// Calculate new position
?CGPoint oldPosition = self.position;
?float xNew = xTarget * kCJTargetFilterFactor + oldPosition.x * (1-kCJTargetFilterFactor);
?float yNew = oldPosition.y + ySpeed;??????self.position = ccp(xNew,yNew);
?// Update the vertical speed
?ySpeed = (ySpeed – kCJGravitySpeed) * kCJSlowDownFactor;
?// Tilt the dragon depending on horizontal speed
?float xDelta = xNew – oldPosition.x;
?self.rotation = xDelta * kCJDeltaToRotationFactor;
?// Check for game over
?if (ySpeed < kCJGameOverSpeed)
?{
?[[GameScene sharedScene] handleGameOver];
?}
}
在Dragon類里我們也需要去控制碰撞。我們將通過(guò)判斷是碰撞了哪種對(duì)象來(lái)相應(yīng)的做出動(dòng)作。如果碰到了錢幣,我們?cè)黾?分?jǐn)?shù)并且給龍一個(gè)向上增長(zhǎng)的速度。如果我們碰到了炸彈,龍會(huì)降低速度并且播放在CocosBuilder里面制作的Hit動(dòng)畫。我們?cè)?userObject里用CCBReader保存的CCBAnimationManager,之后調(diào)用 runAnimationsForSequenceNamed:方法。
- (void) handleCollisionWith:(GameObject *)gameObject
{
?if ([gameObject isKindOfClass:[Coin class]])
?{
?// Took a coin
?ySpeed = kCJCoinSpeed;
?[GameScene sharedScene].score += 1;
?}
?else if ([gameObject isKindOfClass:[Bomb class]])
?{
?// Hit a bomb
?if (ySpeed > 0) ySpeed = 0;
?CCBAnimationManager* animationManager = self.userObject;
?NSLog(@”animationManager: %@”, animationManager);
?[animationManager runAnimationsForSequenceNamed:@"Hit"];
?}
}
最后我們要實(shí)現(xiàn)radius(半徑)屬性。它將用于控制碰撞。
- (float) radius
{
?return 25;
}
完整的Dragon類,請(qǐng)參見:
Dragon.m
Dragon.h
Coin
金幣有一個(gè)相當(dāng)簡(jiǎn)單的邏輯,金幣在碰到龍的時(shí)候會(huì)被移除。如果最后一枚金幣碰撞到了龍,該等級(jí)的任務(wù)完成。創(chuàng)建一個(gè)名為 Coin的類,他是GameObject的子類。在CocosBuilder我們?cè)黾恿艘恍┳远x的屬性,isEndCoin是專門針對(duì)最后一枚金幣的, 普通金幣也使用相同的自定義類。我們需要實(shí)現(xiàn)這個(gè)屬性在我們的類里,下文是頭部文件:
@interface Coin : GameObject
{
?BOOL isEndCoin;
}
@property (nonatomic,assign) BOOL isEndCoin;
@end
.m文件,我們首先要synthesize屬性isEndCoin。
@synthesize isEndCoin;
我們不必移動(dòng)金幣,所以我們不用實(shí)現(xiàn)update方法。但是,當(dāng)背龍碰撞的時(shí)候我們想移除它。并且,如果是最后一枚金幣的話,我們想升級(jí)。
- (void) handleCollisionWith:(GameObject *)gameObject
{
?if ([gameObject isKindOfClass:[Dragon class]])
?{
?if (isEndCoin)
?{
?// Level is complete!
?[[GameScene sharedScene] handleLevelComplete];
?}
?self.isScheduledForRemove = YES;
?}
}
最后,讓我們來(lái)設(shè)定金幣的半徑。
- (float) radius
{
?return 15;
}
完整的代碼,參見下方:
Coin.m
Coin.h
Bomb
炸彈是我們游戲當(dāng)中的一個(gè)障礙物。創(chuàng)建名為Bomb的類,他是GameObject的子類。當(dāng)炸彈碰撞到玩家的時(shí)候,它 會(huì)爆炸。這個(gè)效果是通過(guò)移除炸彈并且動(dòng)態(tài)的加載爆炸效果來(lái)實(shí)現(xiàn)的。我們沒(méi)有添加任何新的屬性進(jìn)來(lái),所以頭文件不需要修改。在.m文件中,我們需要實(shí)現(xiàn) handleCollisionsWith:方法。
- (void) handleCollisionWith:(GameObject *)gameObject
{
?if ([gameObject isKindOfClass:[Dragon class]])
?{
?// Collided with the dragon, remove object and add an explosion instead
?self.isScheduledForRemove = YES;
?CCNode* explosion = [CCBReader nodeGraphFromFile:@"Explosion.ccbi"];
?explosion.position = self.position;
?[self.parent addChild:explosion];
?}
}
之后,我們需要設(shè)定炸彈的半徑。
- (float) radius
{
?return 15;
}
完整的代碼,如下:
Bomb.m
Bomb.h
Explosion
最后一個(gè)游戲?qū)ο?#xff0c;我們將會(huì)實(shí)現(xiàn)爆炸(Explosion)。爆炸不會(huì)影響其他的任何游戲?qū)ο蟆5俏覀儠?huì)在它完成播放 之后移除調(diào)它。為此我們必須實(shí)現(xiàn)CCBAnimationManagerDelegate。在頭文件,首先引入 CCBAnimationManagerDelegate.h,然后將其作為一個(gè)協(xié)議加進(jìn)到Explosion。
#import “CCBAnimationManager.h”
@interface Explosion : GameObject
@end
.m文件,我們將分配Explosion類作為CCBActionManager的代理,這步的創(chuàng)建將發(fā)生在爆炸加載的時(shí)候。我們將在didLoadFromCCB:方法來(lái)實(shí)現(xiàn)這步。
- (void) didLoadFromCCB
{
?// Setup a delegate method for the animationManager of the explosion
?CCBAnimationManager* animationManager = self.userObject;
?animationManager.delegate = self;
}
至此,當(dāng)動(dòng)畫播放完畢我們將收到回調(diào)函數(shù)completedAnimationSequenceNamed:,實(shí)現(xiàn)該回調(diào)并增加一個(gè)移除爆炸的定時(shí)器。
- (void) completedAnimationSequenceNamed:(NSString *)name
{
?// Remove the explosion object after the animation has finished
?self.isScheduledForRemove = YES;
}
完整的代碼見下方:
Explosion.m
Explosion.h
Level
我們就還剩一個(gè)Level類沒(méi)有完成。Level將會(huì)控制所有的玩家輸入,并且負(fù)責(zé)更新和移除我們的游戲?qū)ο蟆?chuàng)建名為L(zhǎng)evel的類,它是CCLayer的子類。在CocosBuilder里,我們添加了一個(gè)成員變量dragon,所以我們要把它加到頭文件。
@class Dragon;??@interface Level : CCLayer
{
?Dragon* dragon;
}
@end
.m文件,我們將引入計(jì)劃訪問(wèn)的類。
#import “Dragon.h”
#import “GameObject.h”
我們也將定義兩個(gè)常量用于層的滾動(dòng)。因?yàn)辇埿枰且恢笨梢姷摹?/p>
#define kCJScrollFilterFactor 0.1
#define kCJDragonTargetOffset 80
我們使用onEnter方法,在每個(gè)frame之前,去提供一個(gè)回調(diào)函數(shù)update:。在onExit我們移除這個(gè)回調(diào)。
- (void) onEnter
{
?[super onEnter];
?// Schedule a selector that is called every frame
?[self schedule:@selector(update:)];
?// Make sure touches are enabled
?self.isTouchEnabled = YES;
}
- (void) onExit
{
?[super onExit];
?// Remove the scheduled selector
?[self unscheduleAllSelectors];
}
在update:方法我們將更新所有游戲?qū)ο蟆S涀?#xff0c;在CocosBuilder里我們?cè)黾拥挠螒驅(qū)ο蠖际莑evel的 子對(duì)象。之后,游戲?qū)ο蟾乱约鞍l(fā)生位置改變的時(shí)候我們將檢測(cè)是否有碰撞。在這個(gè)游戲里我們只檢測(cè)與龍之間的碰撞,因?yàn)橹挥兴且苿?dòng)的。在其他的游戲里, 你可能需要寫更多更復(fù)雜的代碼去檢測(cè)碰撞,或者有可能用到諸如Chipmunk,Box2d的物理引擎。因?yàn)樗械呐鲎捕际强煽氐?#xff0c;我們將會(huì)遍歷游戲的所 有對(duì)象去看哪些對(duì)象被定時(shí)移除了。我們?yōu)檫@些對(duì)象創(chuàng)建一個(gè)數(shù)組,使用這個(gè)隊(duì)列來(lái)移除他們。最后,我們調(diào)整層的位置,所以龍總是可見的。當(dāng)調(diào)整位置的時(shí)候我 們使用過(guò)濾器代理去確保移動(dòng)的平滑。
- (void) update:(ccTime)delta
{
?// Iterate through all objects in the level layer
?CCNode* child;
?CCARRAY_FOREACH(self.children, child)
?{
?// Check if the child is a game object
?if ([child isKindOfClass:[GameObject class]])
?{
?GameObject* gameObject = (GameObject*)child;
?// Update all game objects
?[gameObject update];
?// Check for collisions with dragon
?if (gameObject != dragon)
?{
?if (ccpDistance(gameObject.position, dragon.position) < gameObject.radius + dragon.radius)
?{
?// Notify the game objects that they have collided
?[gameObject handleCollisionWith:dragon];
?[dragon handleCollisionWith:gameObject];
?}
?}
?}
?}
?// Check for objects to remove
?NSMutableArray* gameObjectsToRemove = [NSMutableArray array];
?CCARRAY_FOREACH(self.children, child)
?{
?if ([child isKindOfClass:[GameObject class]])
?{
?GameObject* gameObject = (GameObject*)child;
?if (gameObject.isScheduledForRemove)
?{
?[gameObjectsToRemove addObject:gameObject];
?}
?}
?}
?for (GameObject* gameObject in gameObjectsToRemove)
?{
?[self removeChild:gameObject cleanup:YES];
?}
?// Adjust the position of the layer so dragon is visible
?float yTarget = kCJDragonTargetOffset – dragon.position.y;
?CGPoint oldLayerPosition = self.position;
?float xNew = oldLayerPosition.x;
?float yNew = yTarget * kCJScrollFilterFactor + oldLayerPosition.y * (1.0f – kCJScrollFilterFactor);
?self.position = ccp(xNew, yNew);
}
最后我們需要去做些事情來(lái)響應(yīng)玩家的觸摸。我們實(shí)現(xiàn)了ccTouchesBegan:withEvent:和ccTouchesMoved:withEvent:方法去獲取觸摸位置,以及設(shè)定龍的xTarget屬性。
- (void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
?UITouch* touch = [touches anyObject];
?CGPoint touchLocation = [touch locationInView: [touch view]];
?dragon.xTarget = touchLocation.x;
}
- (void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
?UITouch* touch = [touches anyObject];
?CGPoint touchLocation = [touch locationInView: [touch view]];
?dragon.xTarget = touchLocation.x;
}
完整的代碼請(qǐng)參見:
Level.m
Level.h
總結(jié)
用所有的CocosBuilder文件為游戲創(chuàng)建的類,你應(yīng)該可以在虛擬機(jī)或者真機(jī)上編譯運(yùn)行。很感謝花時(shí)間讀這個(gè)教程,祝你編碼愉快!
總結(jié)
以上是生活随笔為你收集整理的Cocosbuilder使用教程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 《本质思考 · 从底层思维构建解决问题的
- 下一篇: OPCUA标准java实现 Milo库