好,这篇我们来讲解无限循环滚动背景,这个知识已经被讲到烂了,我以前的文章也介绍过,所以就不那么详细地说明了。


笨木头花心贡献,啥?花心?不呢,是用心~

转载请注明,原文地址:http://www.benmutou.com/blog/archives/823

文章来源:笨木头与游戏开发



为什么是循环滚动背景?

用循环滚动背景,其实是因为我想偷懒,因为这样我只需要准备一张图片就可以了。


我们最终要创建这样的背景,如图:


Cocos2d-x3.0游戏实例之《别救我》第三篇-滚动背景

Cocos2d-x3.0游戏实例之《别救我》第三篇-滚动背景


背景是在滚动的,大家有没有看到?(小若:看你妹,这是jpg,不是gif)


大家是不是很在意下面的那多出来的一条锯齿?它可不是坐标错位了,这是一个伏笔(还伏笔,你以为写小说啊!)。


本篇教程会用到的图片资源到这里下载:http://yunpan.cn/QNXxe5fekPy4y  访问密码 8c82


创建2张连续的背景图片

要实现循环滚动的背景,需要2张相同的图片实现,图片首尾相接。


我们要创建一个新的类,叫做BackgroundLayer,用来实现滚动背景。


创建2张相同的背景图片,很简单,代码如下:

 
  1. Size visibleSize = Director::getInstance()->getVisibleSize();

  2. /* 背景图片 */

  3. m_bg1 = Sprite::create("background.jpg");

  4. m_bg1->setPosition(Point(visibleSize.width*0.5f, visibleSize.height*0.5f));

  5. this->addChild(m_bg1);

  6. m_bg2 = Sprite::create("background.jpg");

  7. m_bg2->setPosition(Point(visibleSize.width*0.5f, -visibleSize.height*0.5f));

  8. this->addChild(m_bg2);

m_bg1和m_bg2都是Sprite对象,因为后面要用到,所以直接作为类的成员属性,方便调用。

m_bg1是屏幕居中,m_bg2要紧接着m_bg1的下面,大家感受一下。


创建边缘锯齿

先跑一下题,我们把边缘锯齿也给添加好:

 
  1. /* 创建边缘锯齿 */

  2. auto border = Sprite::create("border.png");

  3. Size borderSize = border->getContentSize();

  4. auto border1 = createBorder(Point(borderSize.width*0.5f, borderSize.height*0.5f));

  5. this->addChild(border1);

  6. auto border2 = createBorder(Point(visibleSize.width- borderSize.width*0.5f, borderSize.height*0.5f));

  7. border2->setFlippedX(true);

  8. this->addChild(border2);

  9. auto border3 = createBorder(Point(visibleSize.width*0.5f, visibleSize.height*0.15f));

  10. borderSize = border3->getContentSize();

  11. border3->setRotation(90.0f);

  12. this->addChild(border3);

一共三个锯齿,左右各一个,下方一个。

createBorder是自定义函数,代码如下:

 
  1. Sprite* BackgroundLayer::createBorder(Point pos)

  2. {

  3. auto border = Sprite::create("border.png");

  4.    Size borderSize = border->getContentSize();

  5. auto body = PhysicsBody::createBox(borderSize);

  6.    body->setDynamic(false);

  7.    body->setCategoryBitmask(1);// 0001

  8.    body->setCollisionBitmask(1);// 0001

  9.    body->setContactTestBitmask(1);// 0001

  10.    border->setPhysicsBody(body);

  11.    border->setPosition(pos);

  12. return border;

  13. }

好,这个函数要稍微解释一下,这里使用PhysicsBody的createBox函数创建实体盒子刚体,因为边缘不是空心的。

然后调用了setDynamic函数,让刚体成为静态物体,也就是说,物理世界不会对它起产生影响了,它不会被撞飞,随你怎么撞,它都纹丝不动~

但是,它会对其他物理对象产生影响,比如有人撞了它,那个人就可能会反弹~


接着,有三个很特别的函数:setCategoryBitmask、setCollisionBitmask、setContactTestBitmask。

这三个函数是用于物体间的碰撞检测的,用来作为判断条件,要解释它们需要不小的篇幅,所以我就不解释了(小若:有没有墙?我想撞一下)

本游戏在碰撞检测方面极其简单,所以不理解这三个函数都完全没有影响,因为游戏里的所有对象都能产生碰撞,没有什么特别的地方。

如果以后有机会,我再单独写一篇文章来介绍吧(或者大家百度一下)


目前的代码

好,来看看目前为止BackgroundLayer的代码,头文件如下:

 
  1. #ifndef BackgroundLayer_H

  2. #define BackgroundLayer_H

  3. #include "cocos2d.h"

  4. USING_NS_CC;

  5. class BackgroundLayer :public Layer

  6. {

  7. public:

  8.    BackgroundLayer();

  9.    ~BackgroundLayer();

  10.    CREATE_FUNC(BackgroundLayer);

  11. virtualbool init();

  12. private:

  13.    Sprite* m_bg1;

  14.    Sprite* m_bg2;

  15.    Sprite* createBorder(Point pos);

  16. };

  17. #endif

Cpp文件如下:
 
  1. #include "BackgroundLayer.h"

  2. BackgroundLayer::BackgroundLayer(){}

  3. BackgroundLayer::~BackgroundLayer(){}

  4. bool BackgroundLayer::init()

  5. {

  6. if(!Layer::init())

  7. {

  8. returnfalse;

  9. }

  10.    Size visibleSize = Director::getInstance()->getVisibleSize();

  11. /* 背景图片 */

  12.    m_bg1 = Sprite::create("background.jpg");

  13.    m_bg1->setPosition(Point(visibleSize.width*0.5f, visibleSize.height*0.5f));

  14.    this->addChild(m_bg1);

  15.    m_bg2 = Sprite::create("background.jpg");

  16.    m_bg2->setPosition(Point(visibleSize.width*0.5f, -visibleSize.height*0.5f));

  17.    this->addChild(m_bg2);

  18. /* 创建边缘锯齿 */

  19. auto border = Sprite::create("border.png");

  20.    Size borderSize = border->getContentSize();

  21. auto border1 = createBorder(Point(borderSize.width*0.5f, borderSize.height*0.5f));

  22.    this->addChild(border1);

  23. auto border2 = createBorder(Point(visibleSize.width- borderSize.width*0.5f, borderSize.height*0.5f));

  24.    border2->setFlippedX(true);

  25.    this->addChild(border2);

  26. auto border3 = createBorder(Point(visibleSize.width*0.5f, visibleSize.height*0.15f));

  27.    borderSize = border3->getContentSize();

  28.    border3->setRotation(90.0f);

  29.    this->addChild(border3);

  30. returntrue;

  31. }

  32. Sprite* BackgroundLayer::createBorder(Point pos)

  33. {

  34. auto border = Sprite::create("border.png");

  35.    Size borderSize = border->getContentSize();

  36. auto body = PhysicsBody::createBox(borderSize);

  37.    body->setDynamic(false);

  38.    body->setCategoryBitmask(1);// 0001

  39.    body->setCollisionBitmask(1);// 0001

  40.    body->setContactTestBitmask(1);// 0001

  41.    border->setPhysicsBody(body);

  42.    border->setPosition(pos);

  43. return border;

  44. }

先测试一下

我们来先测试一下代码的运行情况吧,我们给TollgateScene添加BackgroundLayer层,修改一下TollgateScene的scene函数:

 
  1. Scene* TollgateScene::scene()

  2. {

  3. auto scene = Scene::createWithPhysics();

  4. /* 这里省略了很多代码 */

  5. /* 背景层 */

  6. auto backgroundLayer = BackgroundLayer::create();

  7.    scene->addChild(backgroundLayer, 0);

  8. auto layer = TollgateScene::create();

  9.    scene->addChild(layer, 10);

  10. return scene;

  11. }

OK,这样就可以了,再次运行代码,正常情况下,如图所示:


Cocos2d-x3.0游戏实例之《别救我》第三篇-滚动背景

Cocos2d-x3.0游戏实例之《别救我》第三篇-滚动背景

(小若:这就是一开始的那张图吧?连图片地址都一样好吧)


现在地图是不会滚动的,没意思,我们来开始滚床单…不,不好意思,习惯了(邪恶),是滚动背景才对。


51cto发博客有长度限制?好吧,这篇太长了,分两次发。