Cocos2d-x學習(十二):用cocos2d-x實現MoonWarriors(無限背景滾動的簡單實現)

特別聲明:本文所有圖片資源來源於MoonWarriors cocos2d-html 開源項目


之前總結過一次無線背景滾動的實現方法,基本上是基於cocos2d-html版的MoonWarriors的方法實現的,

博客地址:cocos2d-x學習(九):cocos2d-x 無限背景滾動


其實原理都是類似的,都是通過移動背景圖,造成玩家角色移動的假象,而無限背景滾動就是兩個背景圖,依次排開,移動,判讀是否移除屏幕外,位置更改,循環交替。

在之前的博客中,我是在update()方法中根據時間和背景移動的速度來動態修改位置實現的,然後判讀是否移動到了屏幕外,再修改位置;這樣做沒問題,但是略顯複雜,這是通用的方法,而沒有利用到引擎爲我們提供的便利!

這次我是使用CCMoveBy類來實現的背景移動,在動作執行完之後再回調本方法,調整位置,繼續移動!這樣做的好處是利用cocos2d爲我們提供的類,代碼比較簡單,而且判讀次數明顯減少(之前在每幀update()移動的時候去判斷,而這樣做之後只需要在回調方法中判讀即可)!


當然這次也是參照cocos2d-html版的MoonWarriors的效果,使用了兩層背景,一層圖片精靈,作爲遠景層;一層是TMX格式的地圖,作爲近景層;

(遠景層和近景層就像是在汽車中看到車外的情況,遠處的高山移動緩慢,是遠景層;近處的樹移動迅速,是近景層。這樣有層次的背景,立體效果比較好!)

具體原理就不解釋了,和之前的博客類似。cocos2d-x學習(九):cocos2d-x 無限背景滾動


1.初始化背景代碼:

void GamePlayBGLayer::initBackground()
{
    // 遠景層
    mVisionBGSprite = CCSprite::spriteWithFile("bg01.jpg");
    // 複製精靈,省去讀取文件的步驟
    mVisionBGSpriteRe = CCSprite::spriteWithTexture(mVisionBGSprite->getTexture());
    // 獲取遠景層高度
    mVisionBGHeight = mVisionBGSprite->getContentSize().height - 1;
    // 設置標籤(不是爲了找到對應的精靈對象,而是爲了區分遠景層和近景層)
    mVisionBGSprite->setTag(GAMEPLAY_BG_VISION_LAYER);
    mVisionBGSpriteRe->setTag(GAMEPLAY_BG_VISION_LAYER);
    // 設置錨點爲零點
    mVisionBGSprite->setAnchorPoint(CCPointZero);
    mVisionBGSpriteRe->setAnchorPoint(CCPointZero);
    // 設置位置,從下到上依次排列遠景層和遠景複製層
    mVisionBGSprite->setPosition(CCPointZero);
    mVisionBGSpriteRe->setPosition(ccp(0, mVisionBGHeight));
    
    this->addChild(mVisionBGSprite, 0);
    this->addChild(mVisionBGSpriteRe, 0);
    
    
    // 近景層(步驟同遠景層)
    mCloseRangeBGTiledMap = CCTMXTiledMap::tiledMapWithTMXFile("level01.tmx");
    mCloseRangeBGTiledMapRe = CCTMXTiledMap::tiledMapWithTMXFile("level01.tmx");
    mCloseRangeBGTiledMap->setTag(GAMEPLAY_BG_CLOSE_RANGE_LAYER);
    mCloseRangeBGTiledMapRe->setTag(GAMEPLAY_BG_CLOSE_RANGE_LAYER);
    mCloseRangeBGHeight = mCloseRangeBGTiledMap->getContentSize().height - 1;
    mCloseRangeBGTiledMap->setPosition(CCPointZero);
    mCloseRangeBGTiledMapRe->setPosition(ccp(0, mCloseRangeBGHeight));
    
    this->addChild(mCloseRangeBGTiledMap, 1);
    this->addChild(mCloseRangeBGTiledMapRe, 1);
}

這裏用到了一個小技巧,就是拷貝精靈對象的方法

// 複製精靈,省去讀取文件的步驟
    mVisionBGSpriteRe = CCSprite::spriteWithTexture(mVisionBGSprite->getTexture());
通過mVisionBGSprite的紋理去生成對象,這樣可以省去從本地圖片文件重複讀取的麻煩,當然如果頻繁使用,可以預先加載到CCTextureCache中!


2.下面是無線背景滾動的動作執行的代碼

void GamePlayBGLayer::scrollingToInfinity(CCNode *pBGLayer)
{
    CCAction *scrollAction = NULL;
    
    // 根據遠景層和近景層不同,執行不同的動作(考慮以後會有更多層,所以用switch)
    switch (pBGLayer->getTag()) {
        case GAMEPLAY_BG_VISION_LAYER:
            // 判斷位置,如果完全移動到屏幕之外,則排在當前顯示層之上,循環使用
            if (pBGLayer->getPositionY() <= -mVisionBGHeight) {
                pBGLayer->setPosition(ccpAdd(pBGLayer->getPosition(), ccp(0, 2 * mVisionBGHeight)));
            }
            scrollAction = CCSequence::actions(CCMoveBy::actionWithDuration(15.0f, ccp(0, -mVisionBGHeight)), CCCallFunc::actionWithTarget(this, callfunc_selector(GamePlayBGLayer::scrollingToInfinity)), NULL);
            break;
        
        case GAMEPLAY_BG_CLOSE_RANGE_LAYER:
            if (pBGLayer->getPositionY() <= -mCloseRangeBGHeight) {
                pBGLayer->setPosition(ccpAdd(pBGLayer->getPosition(), ccp(0, 2 * mCloseRangeBGHeight)));
            }
            scrollAction = CCSequence::actions(CCMoveBy::actionWithDuration(12.0f, ccp(0, -mCloseRangeBGHeight)), CCCallFunc::actionWithTarget(this, callfunc_selector(GamePlayBGLayer::scrollingToInfinity)), NULL);
            break;
            
        default:
            CCAssert(0, "錯誤的遊戲場景ID");
            break;
    }
    
    if (scrollAction) {
        pBGLayer->runAction(scrollAction);
    }
}
這裏的switch是爲了區分遠景層和近景層而做的處理,考慮到之後爲了效果可以增加更多的層次!

效果圖

 


項目地址


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