Cocos2d-x学习(九):cocos2d-x 无限背景滚动

最近在学习飞行射击类游戏的一些开发,学到的东西确实不少,比如,无限背景滚动,子弹的缓冲池,面向组件开发等等!

今天就来总结一下无限背景滚动的实现!

飞行类的游戏都是基于背景的滚动,造成视觉上的假象,认为飞机在飞行,而不是“真正的向前飞”。。。


1.原理

滚动的原理:设定一个速度,在每次调用update(ccTime dt) 时,就根据速度和dt得到移动的偏移量,因为更新频率很快,所以偏移量很小,所以在视觉上认为是连贯的!就形成了滚动效果。

无限滚动的原理:有两个背景,每次调用update(ccTime dt) 时,判断当前这两个背景,如果在屏幕之外了,说明它不在起到显示作用,于是将它放到后面去,其实就像是两条腿走路,一前一后,循环,就向前运动起来了,也就是说只需要两个背景,一张贴在一张后面!(我采用的算法比较懒,就是会对两个背景分别判断位置,而不是记录哪个背景在前,哪个背景在后)!


2.代码实现

这里用了两个景层,一个近景,一个远景,这样看起来效果更逼真!(资源来源于cocos2d-x-html版的飞行demo)

远景用了一个图片精灵,近景用了一个tmx地图

定义了一个背景标签,用来标记是近景还是远景,如果只有一层就可以忽略

[cpp]  view plain copy
  1. // 背景标签  
  2. enum TAG_BG  
  3. {  
  4.     TAG_BG_NEAR_LAYER = 0,  
  5.     TAG_BG_FAR_LAYER = 1  
  6. };  
近景和远景精灵,以及其运行速度和景层的高度,(速度用来滚动,高度用来判断更新景层的位置)

[cpp]  view plain copy
  1. private:  
  2.     // 背景(远景层)  
  3.     CCSprite *m_pSkySprite;  
  4.     CCSprite *m_pSkySpriteRe;  
  5.     float m_fSkyVelocity;  
  6.     float m_fSkyHeight;  
  7.       
  8.     // 地图(近景层)  
  9.     CCTMXTiledMap *m_pTileMap;  
  10.     CCTMXTiledMap *m_pTileMapRe;  
  11.     float m_fTileMapVelocity;  
  12.     float m_fTileMapHeight;  
初始化,每个景层由两个相同地图精灵组成,依次排开,向下运动

[cpp]  view plain copy
  1. void GameBGLayer::initBackground()  
  2. {  
  3.     // Sky  
  4.     m_pSkySprite = CCSprite::spriteWithFile("bg01.jpg");  
  5.     m_pSkySpriteRe = CCSprite::spriteWithFile("bg01.jpg");  
  6.     m_pSkySprite->setAnchorPoint(CCPointZero);  
  7.     m_pSkySpriteRe->setAnchorPoint(CCPointZero);  
  8.     this->addChild(m_pSkySprite, -10, TAG_BG_NEAR_LAYER);  
  9.     this->addChild(m_pSkySpriteRe, -10, TAG_BG_NEAR_LAYER);  
  10.       
  11.     // Map  
  12.     m_pTileMap = CCTMXTiledMap::tiledMapWithTMXFile("level01.tmx");  
  13.     m_pTileMapRe = CCTMXTiledMap::tiledMapWithTMXFile("level01.tmx");  
  14.     m_pTileMap->setAnchorPoint(CCPointZero);  
  15.     m_pTileMapRe->setAnchorPoint(CCPointZero);      
  16.     this->addChild(m_pTileMap, -9, TAG_BG_FAR_LAYER);  
  17.     this->addChild(m_pTileMapRe, -9, TAG_BG_FAR_LAYER);  
  18.       
  19.     // 设置高度  
  20.     m_fSkyHeight = m_pSkySprite->getContentSize().height;  
  21.     m_fTileMapHeight = m_pTileMap->getMapSize().height * m_pTileMap->getTileSize().height;  
  22.       
  23.     // 设置副本背景位置  
  24.     m_pSkySpriteRe->setPosition(ccp(0, m_fSkyHeight));  
  25.     m_pTileMapRe->setPosition(ccp(0, m_fTileMapHeight));  
  26.       
  27.     // 设置移动速度  
  28.     m_fSkyVelocity = -16;  
  29.     m_fTileMapVelocity = -60;  
  30. //    m_fSkyVelocity = -160;  
  31. //    m_fTileMapVelocity = -600;  
  32. }  
更新方法,为了统一管理,我将所有背景相关的都放在了这一层,每次遍历并更新位置和判断是否向后移动

[cpp]  view plain copy
  1. void GameBGLayer::update(ccTime dt)  
  2. {  
  3.     CCArray *bgSprites = this->getChildren();  
  4.     CCObject *obj = NULL;  
  5.       
  6.     CCARRAY_FOREACH(bgSprites, obj)  
  7.     {  
  8.         movingBackground(obj, dt);  
  9.     }  
  10. }  
移动背景(包括滚动和向后移动)

[cpp]  view plain copy
  1. void GameBGLayer::movingBackground(CCObject *pObj, ccTime dt)  
  2. {  
  3.     CCNode *bgNode = (CCNode*) pObj;  
  4.     int tag = bgNode->getTag();  
  5.       
  6.     if (tag == TAG_BG_NEAR_LAYER) {  
  7.         // 远景层  
  8.         bgNode->setPositionY(bgNode->getPositionY() + m_fSkyVelocity * dt);  
  9.         if (bgNode->getPositionY() < -m_fSkyHeight) {  
  10.             bgNode->setPositionY(bgNode->getPositionY() + m_fSkyHeight * 2 - 2);  
  11.         }  
  12.     }  
  13.     else if (tag == TAG_BG_FAR_LAYER) {  
  14.         // 近景层  
  15.         bgNode->setPositionY(bgNode->getPositionY() + m_fTileMapVelocity * dt);  
  16.         if (bgNode->getPositionY() < -m_fTileMapHeight) {  
  17.             bgNode->setPositionY(bgNode->getPositionY() + m_fTileMapHeight * 2 - 2);  
  18.         }  
  19.     }  
  20. }  

-2的目的是为了避免背景之间有可能因为加载产生的黑线


3.效果



不能做成动画,效果看不出来。。。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值