如何製作一個基於Tile的遊戲 Cocos2d-x 2.0.4

來源:互聯網
上載者:User

      本文實踐自 Ray Wenderlich 的文章《How To Make a Tile-Based Game with Cocos2D》,文中使用Cocos2D,我在這裡使用Cocos2D-x 2.0.4進行學習和移植。這個遊戲是關於一個忍者在沙漠中尋找西瓜的故事。
      在這部分內容,將會學習到如何用Tile建立一個地圖,如何載入地圖到遊戲,如何讓地圖跟隨玩家滾動,以及如何使用對象層。下一部分內容,將介紹如何在地圖中建立可碰撞的地區,如何使用Tile屬性,如何建立可拾取的物品和動態修改地圖,以及如何確保忍者不會吃撐掉。
 
步驟如下:
1.建立Cocos2d-win32工程,工程名為"TileGame",去除"Box2D"選項,勾選"Simple Audio Engine in Cocos Denshion"選項;
2.下載本遊戲所需的資源,將資源放置"Resources"目錄下;

3.使用Tiled工具製作地圖。首先,下載開源的Tiled Map Editor工具,目前的版本為0.8.1,建議使用QT版本。在Tiled工具,點擊功能表列→"檔案"→"新檔案",在彈出的對話方塊中,填入如下內容:

地圖方向分為:正常、45度。地圖大小填入的是tile單位。塊大小是資源每個tile的實際像素大小,在本篇中,使用32x32大小。點擊"確定"。
4.接著,把所需要的tile集合加入到工具中。功能表列→"地圖"→"新圖塊",填入如下內容:

點擊"瀏覽",選擇"Resources"目錄下的tmw_desert_spacing.png檔案,會自動填滿"名稱"內容。塊的寬高都為32像素。邊距就是當前tile塊開始計算實際像素時,應該跳過多少像素,寬高一樣。間距就是兩個tile塊之間的像素距離,寬高一樣。看看tmw_desert_spacing.png檔案,可以看到每個tile塊都1像素的黑色邊框,這就是為什麼要設定邊距和間距為1像素。

點擊"確定"。
5.可以看到tile塊出現在"圖塊"視窗中。現在可以開始畫地圖。點擊功能表列→"視圖"→"顯示網格",可以開啟網格參照線。點擊工具列"圖章刷",然後在"圖塊"視窗點選一個tile塊,接著在地圖中,點擊放入你所想要的位置。

用工具列"填充",把地圖背景填充成同一個tile塊,這裡為沙漠背景。可以從"圖塊"視窗點選多個tile塊,可按Ctrl鍵多選,這樣可以一次性將多個tile塊放入地圖中。進行製作地圖,確保至少有一對建築在地圖上,因為後面需要一些東西來做碰撞。一旦完成了地圖的製作,雙擊"圖層"視窗中的當前層"塊層
1",重新命名為"Background"。然後點擊工具列"儲存",命名為"TileMap.tmx",儲存在"Resources"目錄下。

6.將Tile地圖加入到情境中。在HelloWorldScene.h檔案中,添加如下代碼:

1
2
CC_SYNTHESIZE_RETAIN(cocos2d::CCTMXTiledMap*, _tileMap, TileMap);
CC_SYNTHESIZE_RETAIN(cocos2d::CCTMXLayer*, _background, Background);

HelloWorldScene.cpp檔案中,建構函式添加如下:

1
2
3
4
5
HelloWorld::HelloWorld()
{
    _tileMap = NULL;
    _background = NULL;
}

初始化init函數,修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool HelloWorld::init()
{
    bool bRet = false;
    do 
    {    
        CC_BREAK_IF(! CCLayer::init());

        this->setTileMap(CCTMXTiledMap::create("TileMap.tmx"));
        this->setBackground(_tileMap->layerNamed("Background"));
        this->addChild(_tileMap, -1);
        bRet = true;
    } while (0);

    return bRet;
}

7.編譯運行,可以看到整個地圖的左下角,如所示:

要讓它成為一個遊戲,還需要三件事:玩家、玩家初始點、行動裝置檢視以便能夠看到玩家。
8.Tiled支援兩種類型層:tile層和對象層。對象層允許你在地圖上可能發生事件的地區繪製矩形。比如:你可能需要一個怪物出生地區,或者一個一進入就會掛掉的地區。在這裡,我們給玩家建立一個出生地。功能表列→"圖層"→"添加對象層",命名為"Objects",點擊工具列"插入對象",在地圖上選擇一個位置並點擊它,這時會出現一個灰色的矩形框,右鍵選擇"對象屬性",名稱填入"SpawnPoint",如所示:


按"確定"按鈕。儲存地圖。
9.在HelloWorldScene.h檔案中,添加如下聲明:

1
CC_SYNTHESIZE_RETAIN(cocos2d::CCSprite*, _player, Player);

HelloWorldScene.cpp建構函式中,添加如下:

1
_player = NULL;

init初始化函數,添加如下:

1
2
3
4
5
6
7
8
9
10
11
12
CCTMXObjectGroup *objects = _tileMap->objectGroupNamed("Objects");
CCAssert(objects != NULL, "Objects' object group not found");
CCDictionary *spawnPoint = objects->objectNamed("SpawnPoint");
CCAssert(spawnPoint != NULL, "SpawnPoint object not found");
int x = spawnPoint->valueForKey("x")->intValue();
int y = spawnPoint->valueForKey("y")->intValue();

this->setPlayer(CCSprite::create("Player.png"));
_player->setPosition(ccp(x, y));
this->addChild(_player);

this->setViewpointCenter(_player->getPosition());

添加一個方法setViewpointCenter,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void HelloWorld::setViewpointCenter(CCPoint position)
{
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();

    int x = MAX(position.x, winSize.width / 2);
    int y = MAX(position.y, winSize.height / 2);
    x = MIN(x, (_tileMap->getMapSize().width * _tileMap->getTileSize().width) - winSize.width / 2);
    y = MIN(y, (_tileMap->getMapSize().height * _tileMap->getTileSize().height) - winSize.height / 2);
    CCPoint actualPosition = ccp(x, y);

    CCPoint centerOfView = ccp(winSize.width / 2, winSize.height / 2);
    CCPoint viewPoint = ccpSub(centerOfView, actualPosition);
    this->setPosition(viewPoint);
}

使用者傳任何的座標過來,但是有一些點不希望顯示出來,比如,我們不想螢幕移出地圖邊界,那裡只是一片空白。

攝像機的中心若是小於winSize.width/2或winSize.height/2,部分的視圖將會在螢幕之外。同樣的,我們需要檢查邊界條件。到目前為止,我們一直把這個函數看作是設定攝像機中心的位置。但是,這並不是我們實際做的。實際做的是移動整個層。看:

想象一下,身處在一個巨大的世界中,我們能看到的地區是從0到winSize.height/width的這部分。我們視野的中心是centerOfView,並且我們知道要讓中心在哪兒(actualPosition)。所以要讓我們視野的中心向上向右移動到actualPosition,我們只需要讓地圖相對的向下向左移動即可。這一步是通過actualPosition與centerOfView座標相減得到的,然後把HelloWorld層的座標設為這個結果。
10.編譯運行,可以看到忍者在螢幕中,如所示:

11.接下來,讓忍者可以移動。在HelloWorldScene.cpp檔案init函數中,添加如下代碼:

1
this->setTouchEnabled(true);

開啟觸摸,然後重載registerWithTouchDispatcher函數,代碼如下:

1
2
3
4
void HelloWorld::registerWithTouchDispatcher(void)
{
     CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
}

註冊觸摸事件,這樣單點觸摸ccTouchBegan和ccTouchEnded會被調用。重載ccTouchBegan函數,代碼如下:

1
2
3
4
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
    return true;
}

返回true表明接受這個觸摸。添加setPlayerPosition方法,來設定玩家座標,代碼如下:

1
2
3
4
void HelloWorld::setPlayerPosition(CCPoint position)
{
    _player->setPosition(position);
}

重載ccTouchEnded方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
void HelloWorld::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
    CCPoint touchLocation = this->convertTouchToNodeSpace(pTouch);

    CCPoint playerPos = _player->getPosition();
    CCPoint diff = ccpSub(touchLocation, playerPos);
    if (abs(diff.x) > abs(diff.y))
    {
        if (diff.x > 0)
        {
            playerPos.x += _tileMap->getTileSize().width;
        } 
        else
        {
            playerPos.x -= _tileMap->getTileSize().width;
        }
    } 
    else
    {
        if (diff.y > 0)
        {
            playerPos.y += _tileMap->getTileSize().height;
        } 
        else
        {
            playerPos.y -= _tileMap->getTileSize().height;
        }       
    }
    
    if (playerPos.x <= (_tileMap->getMapSize().width * _tileMap->getTileSize().width) &&
        playerPos.y <= (_tileMap->getMapSize().height * _tileMap->getTileSize().height) &&
        playerPos.y >= 0 && playerPos.x >= 0)
    {
        setPlayerPosition(playerPos);
    }
    
    setViewpointCenter(_player->getPosition());
}

計算觸摸點與玩家座標之間的差值,來決定玩家的移動方向。
12.編譯運行,點擊螢幕,讓忍者動起來,如所示:

參考資料:
1.How To Make a Tile-Based Game with Cocos2D

http://www.raywenderlich.com/1163/how-to-make-a-tile-based-game-with-cocos2d

2.如何使用Cocos2D製作一款基於tile的遊戲

http://www.raywenderlich.com/zh-hans/16771/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8cocos2d%E5%88%B6%E4%BD%9C%E4%B8%80%E6%AC%BE%E5%9F%BA%E4%BA%8Etile%E7%9A%84%E6%B8%B8%E6%88%8F

3.(譯)如何使用cocos2d製作基於tile地圖的遊戲教程:第一部分

http://www.cnblogs.com/zilongshanren/archive/2011/04/11/2012852.html

非常感謝以上資料,本例子原始碼附加資源:http://download.csdn.net/detail/akof1314/4966622
如文章存在錯誤之處,歡迎指出,以便改正。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.