首页 > 代码库 > Cocos2d-x3.0游戏实例之《别救我》第三篇——循环滚动背景(下)

Cocos2d-x3.0游戏实例之《别救我》第三篇——循环滚动背景(下)

51cto对文章长度有限制,所以第三篇分开两次来发。


统一控制游戏逻辑

地图滚动,其实就是不断改变2张地图的坐标,要不断改变坐标,就要用schedule来实现,schedule可以在游戏每一帧或者每隔一段时间的时候执行一次逻辑,这个如果不了解的,可以看看我的另外几篇关于schedule的文章:

【木头Cocos2d-x 032】我是定时器(第01章)—我爱单线程之schedule介绍

【木头Cocos2d-x 033】我是定时器第02章—HelloWorld之scheduleUpdate

【木头Cocos2d-x 034】我是定时器(第03章)—真正的定时器之schedule

【木头Cocos2d-x 035】我是定时器(第04章)—停止update和触发器


木头我有一个坏习惯,那就是把游戏中所有的逻辑都用一个schedule来完成,这么说有点模糊,直接看代码吧。


首先给TollgateScene添加一个logic函数:

  1. class TollgateScene :public Layer

  2. {

  3. public:

  4.    ~TollgateScene();

  5. static Scene* scene();

  6.    CREATE_FUNC(TollgateScene);

  7. virtualbool init();

  8. virtualvoid onExit() override;

  9. private:

  10. void logic(float dt);

  11.    BackgroundLayer* m_backgroundLayer;

  12. };

  13. #endif

以及我偷偷添加了一个BackgroundLayer成员变量,大有用处,不要着急~

然后修改一下TollgateScene的scene函数:

  1. Scene* TollgateScene::scene()

  2. {

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

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

  5. /* 背景层 */

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

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

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

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

  10.    layer->m_backgroundLayer = backgroundLayer;

  11. return scene;

  12. }

留意最后一句代码(小若:是倒数第二句!),好吧,倒数第二句,我们保留了BackgroundLayer的引用。也许这样保持引用是比较糟糕的做法,或许用getChildByTag的方式来获取BackgroundLayer会好一些,但因为这对象要使用很多次,我选择了直接保存引用。大家根据个人喜好来决定吧~


OK,最重要的,看看TollgateScene的logic函数实现,有点复杂,大家要有心理准备:

  1. void TollgateScene::logic(float dt)

  2. {

  3.    m_backgroundLayer->logic(dt);

  4. }

(小若:= =哇,好复杂啊,完全看不懂….(蛇精病))


我想,大家已经理解我之前说的,统一控制逻辑的意思了吧?由TollgateScene场景来调用各个层的logic函数,这样很方便,要停止逻辑的时候,只要由TollgateScene控制一下就可以了,不需要对各个层单独地进行控制。


OK,别忘了,在TollgateScene的init函数加上schedule的调用:

  1. bool TollgateScene::init()

  2. {

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

  4. {

  5. returnfalse;

  6. }

  7.    this->schedule(schedule_selector(TollgateScene::logic));

  8. returntrue;

  9. }

BackgroundLayer背景层的逻辑

好了,我们还得为BackgroundLayer添加一个logic逻辑处理函数,头文件添加函数声明:

  1. class BackgroundLayer :public Layer

  2. {

  3. public:

  4.    BackgroundLayer();

  5.    ~BackgroundLayer();

  6.    CREATE_FUNC(BackgroundLayer);

  7. virtualbool init();

  8. void logic(float dt);

  9. private:

  10.    Sprite* m_bg1;

  11.    Sprite* m_bg2;

  12.    Sprite* createBorder(Point pos);

  13. };

BackgroundLayer的logic函数实现如下,这个就真的有点小复杂了:

  1. void BackgroundLayer::logic(float dt){

  2. int posY1 = m_bg1->getPositionY();// 背景地图1的Y坐标

  3. int posY2 = m_bg2->getPositionY();// 背景地图2的Y坐标

  4. int iSpeed =3;// 地图滚动速度

  5. /* 两张地图向上滚动(两张地图是相邻的,所以要一起滚动,否则会出现空隙) */

  6.    posY1 += iSpeed;

  7.    posY2 += iSpeed;

  8. /* 屏幕宽 */

  9. int iVisibleHeight = Director::getInstance()->getVisibleSize().height;

  10. /* 当第1个地图完全离开屏幕时,让第2个地图完全出现在屏幕上,同时让第1个地图紧贴在第2个地图后面 */

  11. if(posY1 > iVisibleHeight *1.5f){

  12.        posY2 = iVisibleHeight *0.5f;

  13.        posY1 =-iVisibleHeight *0.5f;

  14. }

  15. /* 同理,当第2个地图完全离开屏幕时,让第1个地图完全出现在屏幕上,同时让第2个地图紧贴在第1个地图后面 */

  16. if(posY2 > iVisibleHeight *1.5f){

  17.        posY1 = iVisibleHeight *0.5f;

  18.        posY2 =-iVisibleHeight *0.5f;

  19. }

  20.    m_bg1->setPositionY(posY1);

  21.    m_bg2->setPositionY(posY2);

  22. }

原理我就不解释了,大家看看代码注释,然后自己在纸上画一画,很好理解的。反正目的就是让两张背景不断往上移动,一旦图片完全离开屏幕,就让它回到屏幕下方,然后又继续往上移动。


好了,现在运行游戏,就能看到背景在滚动了~


OK,下一篇我们就正式加入主角了。