最近在学习飞行射击类游戏的一些开发,学到的东西确实不少,比如,无限背景滚动,子弹的缓冲池,面向组件开发等等!
今天就来总结一下无限背景滚动的实现!
飞行类的游戏都是基于背景的滚动,造成视觉上的假象,认为飞机在飞行,而不是“真正的向前飞”。。。
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.效果
不能做成动画,效果看不出来。。。