轉的 在這個分為上下兩部分的教程中,我們將介紹如何使用Cocos2D-X和地圖編輯器做一款基于地圖塊的游戲。在這個簡單的地圖塊游戲里,一個精靈將在沙漠里搜尋它可口的西瓜!
- 在教程的第一部分,我們將介紹如何創建一個地圖,如何將地圖添加到游戲中,如何滾動地圖以跟著玩家跑,以及如何使用對象層。
- 在本教程的第二部分,我們將介紹如何在地圖上制作碰撞區,如何使用地圖塊的屬性,如何制作寶藏并動態的修改地圖,以及如何確保你的忍者不暴飲暴食。
如果你還沒有學習“如何用cocos2d-x來開發簡單的Uphone游戲:(一) 下載安裝和HelloWorld ”,你不妨先學習下這個教程,因為這個教程里有很多基礎知識我們下面要用到。
好吧,讓我們開始探險之旅吧!
創建一個工程框架
我們將首先創建一個框架工程,以確保我們擁有下面工程中所需的所有文件。
先下載并運行helloworld(具體參見教程“如何用cocos2d-x來開發簡單的Uphone游戲:(一) 下載安裝和HelloWorld ”)。
接下來,下載游戲所需要的zip資源文件(TileGameResource.zip)。該zip文件包含以下內容
• 一個我們將作為游戲主角的精靈。這個和教程“如何用cocos2d-x來開發簡單的Uphone游戲:(二) 移動的精靈”很像!
• 聲音特效,用cxfr工具制作(by Wenderlich)。
• 一些背景音樂,用Garage Band制作(by Wenderlich,更多信息見post)。
• 地圖塊 - 這實際上是要用地圖編輯器做的,但現在就把它和其他東西一起包含進來會更容易一些。
• 一些其他“特殊”的地圖塊,我們將在下面介紹。
好了,這些資源將在后面適當的時候添加到我們的游戲中,現在就是我們制作地圖和享受樂趣的時刻了!
Cocos2DX支持由開源項目地圖塊圖編輯器(Tiled Map Editor,國外網站,需要FQ)制作并保存為TMX格式的地圖。
如果你訪問上面的鏈接,你會看到有兩個版本的編輯器 – 一種是用Qt應用程序框架編寫的,另一種是用Java編寫的。有兩個版本的原因是因為這個編輯器最先是用Java編寫的,后來他們又將它移植到Qt上來。
你要用哪個版本主要是取決于你。在本教程中,我們將介紹使用Qt版本,因為從現在開始這是編輯器的發展主線,但有些人又喜歡用Java版本,因為并不是所有的舊功能都已經被移植過來了。
不管怎樣 - 如果你想跟著學習,那就下載Qt版本,然后安裝運行。轉到文件\新建,在對話框中填寫如下:
在新建地圖對話框的Orientation選項,你可以選擇Orthogonal(正交視圖,采用的游戲Legend of Zelda)或者Isometric(等軸視圖,采用的游戲Disgaea),這里,我們選擇Orthogonal。
下面你得到設定地圖大小。記住這是以地圖塊為單位,不是像素點。我們要做一張比較小的地圖,因此就選擇50×50。
最后設定地圖塊的寬度和高度。在這里你選擇多大的尺寸是依賴于你的美工制作的地圖塊的大小的。在本教程中,我們用的是編輯器中附帶的示例地圖塊集,每個地圖塊都是32×32大小的,因此選擇32×32。
接下來,我們就在編輯器中加入地圖塊集。點擊菜單欄的“Map”選項,選擇“New Tileset…”,然后填寫對話框:
圖片可以點擊Browse按鈕得到,點擊后導航到你的地圖編輯器目錄下的examples文件夾,將tmw_desert_spacing.png加到工程中.
寬度和高度32×32不用改,那個就是地圖塊的寬高。對于margin and spacing(邊際和間距),還沒有確切解釋它們意思的文獻,但它們應該這么理解:
• 邊緣,指的是一個地圖塊的外面一圈,在這個邊緣里面是實際的地圖塊內容。
• 間隔,即兩個地圖塊之間的間距(像素單位)。
如果你看一看tmw_desert_spacing.png,你會發現每個地圖塊有一個1像素的黑邊界,這就解釋了邊際和間距為什么設置作為1。
一旦你點擊OK,你就將在Tilesets窗口看見地圖塊集。Ok,現在你也能開始畫地圖了! 點擊在工具欄的“Stamp”圖標,點擊一個地圖塊,然后在地圖上任意一個你想要的地方點擊填充地圖塊。
繼續完成你的地圖吧——但一定要發揮你的想象力噢! 但請在地圖上至少畫一兩個建筑物,因為待會我們會讓我們的精靈走進你造的建筑。
這里有幾個制圖的小竅門,可以記住:
• 你可以在Tileset中拖動鼠標,同時選擇幾個地圖塊,然后填充到地圖上。
• 你可以使用工具欄上的油漆桶按鈕來填充一整片具有同樣背景的地圖,當然,用來填充的地圖塊是你在Tileset選擇的。
• 你可以通過“查看\放大...”和“查看\縮小...”放大和縮小地圖。
一旦你繪制完地圖,在圖層窗口中單擊當前圖層(現在這個圖層就是“tile layer 1”),將名稱改為“background”。然后點擊“File\Save”,將文件保存到你的TileMap項目資源文件夾,并命名該文件“tilemap.tmx”。
我們后面還將做更多的東西,但現在讓我們把這張地圖加載到游戲中!
把地圖加載到Cocos2DX場景中
首先,因為我們是利用uphone的sdk開發游戲,所以我們先將資源也就是tilemap.tmx和tmw_desert_spacing.png拷貝到sdk所在目錄的子目錄“/UserData/”中。
然后,將HelloWorld.cpp的initCocos2d()函數用下面的代碼替換:
{
// init director
CCDirector::getSharedDirector()->setOpenGLView(m_pMainWnd);
// set to landscape mode
CCDirector::getSharedDirector()->setDeviceOrientation(kCCDeviceOrientationLandscapeLeft);
// load the tile map
CCTMXTiledMap *pDesertTileMap = CCTMXTiledMap::tiledMapWithTMXFile("tilemap.tmx");
pDesertTileMap->setPosition(CGPoint(0,0));
// create layer instance
CCLayer *pLayer = MyLayer::node();
pLayer->addChild(pDesertTileMap, 0, 1);
// add layer to scene
CCScene *pScene = CCScene::node();
pScene->addChild(pLayer);
// add scene to director
CCDirector::getSharedDirector()->runWithScene(pScene);
return true;
}
在這里,我們用到了CCTMXTiledMap類,通過它加載了我們制作的地圖。
現在大概的介紹下CCTMXTiledMap。這是一個CCNode,所以你可以設置它的位置,尺寸等,該節點的子節點是地圖上的層,而且也有 一個接口可以通過名字來獲取這些層,比如這里的“background”層。每一個層都是CCSpriteSheet的子類,這也意味著每一層你只能有一 個tileset。
所以我們在這里做的是保存tilemap和background的關系,并且把tilemap加到HelloWorld的layer上去。
這樣就很ok了!編譯和運行代碼,你應該看到的是你地圖的左下角:
還不賴! 但我們做的是游戲,所以我們還需要做三件事: a)一個精靈, b)精靈的出生點 和c)移動我們的視圖,以便我們可以看到精靈。
這是我們會感到棘手的地方,下面我們就來解決掉它!
對象層和地圖位置的設置
地圖模塊支持兩種層,一種是地圖層(就是我們上面一直在接觸的),另一種是對象層。
對象層允許你在地圖指定一個位置,在這個位置可以響應一些事件。比如,你希望有一個地方讓精靈出生或者掛掉。在我們的教程中,我們要創建一個精靈的出生點。
那么,選擇菜單欄中的“Layer\Add Object Layer…”,將該層命名為“objects”,然后單擊確定。現在如果你在地圖上畫,你會發現它不是直接畫地圖塊,而是畫一個形狀怪異的灰色框框,你可以放縮和移動這個灰色框框。
我們只是想選一個位置來放置我們的精靈,所以在地圖上隨便選一個位置單擊。框框的大小并不重要,因為我們只需要用到x,y坐標。
然后右鍵單擊灰色框框和點擊“Properties”,命名為“spawnpoint”,點擊OK :
假如你在這里設置了對象的類(Cocos2DX的類,比如CCSprite),那么代碼會自動創建一個對應類型的對象。(不過GeekAndDad.com的泰勒指出,這是Cocos2DX以前的版本才具有的功能,現在已經被刪除了。)
不管怎樣,我們將type置空,那么它將為我們創建一個NSMutableDictionary,我們可以通過它訪問該對象的各個屬性,包括X,Y坐標。
保存地圖并返回到代碼,在HelloWorld.cpp的initCocos2d()接口中,在代碼:
CCTMXTiledMap *pDesertTileMap = CCTMXTiledMap::tiledMapWithTMXFile("tilemap.tmx");
pDesertTileMap->setPosition(CGPoint(0,0));
的下面,加入以下代碼
CCTMXObjectGroup *objGroup = pDesertTileMap->objectGroupNamed("objects");
CCXStringToStringDictionary *spawnPoint = objGroup->objectNamed("spawnpoint");
float fSpawnPointX = spawnPoint->objectForKey("x")->toFloat();
float fSpawnPointY = spawnPoint->objectForKey("y")->toFloat();
// load player image texture
CCTexture2D *pPlayerTexture = CCTextureCache::sharedTextureCache()->addImage("Player.png");
// create sprite instance
CCSprite *pPlayer = CCSprite::spriteWithTexture(pPlayerTexture);
pPlayer->setPosition(CGPoint(fSpawnPointX, fSpawnPointY));
// add the player to the tile map
pDesertTileMap->addChild(pPlayer);
Ok,我們再解釋一下對象層和對象組。在這里,我們通過CCTMXTiledMap對象的objectGroupNamed接口得到了對象層,它返回的是一個CCTMXObjectGroup對象。
然后,我們通過CCTMXObjectGroup的objectNamed方法來得到一個NSMutableDictionary,它包含了對 象層的對象的一堆有用的信息,包括X和Y坐標,寬度和高度。不過這里我們關心的是X,Y坐標,所以我們就只取得X,Y坐標,并把它作為精靈的位置。
編譯運行代碼我們就可以看到精靈了。
下面我們再讓它動一動。在代碼
CCDirector::getSharedDirector()->runWithScene(pScene);
的下面,添加代碼:
CCIntervalAction *move = CCMoveBy::actionWithDuration(5, ccp(140, 120));
CCIntervalAction *back = move->reverse();
CCFiniteTimeAction *seq = CCSequence::actions(move, back,NULL);
pPlayer->runAction( CCRepeatForever::actionWithAction((CCIntervalAction*) seq) );
這里的幾個action類是對動作的封裝。上面代碼的含義是表示精靈將向右上方移動,相對位置是(140, 120),并在五秒鐘內完成移動,然后反方向移回到原來位置。
Ok,先運行你的代碼,然后欣賞你的精靈開心的跑來跑去吧!
文章列表