Cocos2d-x學習(九):cocos2d-x 無限背景滾動

最近在學習飛行射擊類遊戲的一些開發,學到的東西確實不少,比如,無限背景滾動,子彈的緩衝池,面向組件開發等等!

今天就來總結一下無限背景滾動的實現!

飛行類的遊戲都是基於背景的滾動,造成視覺上的假象,認爲飛機在飛行,而不是“真正的向前飛”。。。


1.原理

滾動的原理:設定一個速度,在每次調用update(ccTime dt) 時,就根據速度和dt得到移動的偏移量,因爲更新頻率很快,所以偏移量很小,所以在視覺上認爲是連貫的!就形成了滾動效果。

無限滾動的原理:有兩個背景,每次調用update(ccTime dt) 時,判斷當前這兩個背景,如果在屏幕之外了,說明它不在起到顯示作用,於是將它放到後面去,其實就像是兩條腿走路,一前一後,循環,就向前運動起來了,也就是說只需要兩個背景,一張貼在一張後面!(我採用的算法比較懶,就是會對兩個背景分別判斷位置,而不是記錄哪個背景在前,哪個背景在後)!


2.代碼實現

這裏用了兩個景層,一個近景,一個遠景,這樣看起來效果更逼真!(資源來源於cocos2d-x-html版的飛行demo

遠景用了一個圖片精靈,近景用了一個tmx地圖

定義了一個背景標籤,用來標記是近景還是遠景,如果只有一層就可以忽略

// 背景標籤
enum TAG_BG
{
    TAG_BG_NEAR_LAYER = 0,
    TAG_BG_FAR_LAYER = 1
};
近景和遠景精靈,以及其運行速度和景層的高度,(速度用來滾動,高度用來判斷更新景層的位置)

private:
    // 背景(遠景層)
    CCSprite *m_pSkySprite;
    CCSprite *m_pSkySpriteRe;
    float m_fSkyVelocity;
    float m_fSkyHeight;
    
    // 地圖(近景層)
    CCTMXTiledMap *m_pTileMap;
    CCTMXTiledMap *m_pTileMapRe;
    float m_fTileMapVelocity;
    float m_fTileMapHeight;
初始化,每個景層由兩個相同地圖精靈組成,依次排開,向下運動

void GameBGLayer::initBackground()
{
    // Sky
    m_pSkySprite = CCSprite::spriteWithFile("bg01.jpg");
    m_pSkySpriteRe = CCSprite::spriteWithFile("bg01.jpg");
    m_pSkySprite->setAnchorPoint(CCPointZero);
    m_pSkySpriteRe->setAnchorPoint(CCPointZero);
    this->addChild(m_pSkySprite, -10, TAG_BG_NEAR_LAYER);
    this->addChild(m_pSkySpriteRe, -10, TAG_BG_NEAR_LAYER);
    
    // Map
    m_pTileMap = CCTMXTiledMap::tiledMapWithTMXFile("level01.tmx");
    m_pTileMapRe = CCTMXTiledMap::tiledMapWithTMXFile("level01.tmx");
    m_pTileMap->setAnchorPoint(CCPointZero);
    m_pTileMapRe->setAnchorPoint(CCPointZero);    
    this->addChild(m_pTileMap, -9, TAG_BG_FAR_LAYER);
    this->addChild(m_pTileMapRe, -9, TAG_BG_FAR_LAYER);
    
    // 設置高度
    m_fSkyHeight = m_pSkySprite->getContentSize().height;
    m_fTileMapHeight = m_pTileMap->getMapSize().height * m_pTileMap->getTileSize().height;
    
    // 設置副本背景位置
    m_pSkySpriteRe->setPosition(ccp(0, m_fSkyHeight));
    m_pTileMapRe->setPosition(ccp(0, m_fTileMapHeight));
    
    // 設置移動速度
    m_fSkyVelocity = -16;
    m_fTileMapVelocity = -60;
//    m_fSkyVelocity = -160;
//    m_fTileMapVelocity = -600;
}
更新方法,爲了統一管理,我將所有背景相關的都放在了這一層,每次遍歷並更新位置和判斷是否向後移動

void GameBGLayer::update(ccTime dt)
{
    CCArray *bgSprites = this->getChildren();
    CCObject *obj = NULL;
    
    CCARRAY_FOREACH(bgSprites, obj)
    {
        movingBackground(obj, dt);
    }
}
移動背景(包括滾動和向後移動)

void GameBGLayer::movingBackground(CCObject *pObj, ccTime dt)
{
    CCNode *bgNode = (CCNode*) pObj;
    int tag = bgNode->getTag();
    
    if (tag == TAG_BG_NEAR_LAYER) {
        // 遠景層
        bgNode->setPositionY(bgNode->getPositionY() + m_fSkyVelocity * dt);
        if (bgNode->getPositionY() < -m_fSkyHeight) {
            bgNode->setPositionY(bgNode->getPositionY() + m_fSkyHeight * 2 - 2);
        }
    }
    else if (tag == TAG_BG_FAR_LAYER) {
        // 近景層
        bgNode->setPositionY(bgNode->getPositionY() + m_fTileMapVelocity * dt);
        if (bgNode->getPositionY() < -m_fTileMapHeight) {
            bgNode->setPositionY(bgNode->getPositionY() + m_fTileMapHeight * 2 - 2);
        }
    }
}

-2的目的是爲了避免背景之間有可能因爲加載產生的黑線


3.效果



不能做成動畫,效果看不出來。。。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章