Cocos2d-x3.0游戏实例《不要救我》三——背景滚动周期
好。让我们来解释一下这个无限循环滚动的背景。这方面的知识一直讲到烂。我以前的文章还介绍了。所以不是那么特别清楚。
笨木头花心贡献,啥?花心?不呢,是用心~
转载请注明,原文地址:http://www.benmutou.com/blog/archives/823
文章来源:笨木头与游戏开发
为什么是循环滚动背景?
用循环滚动背景,事实上是由于我想偷懒,由于这样我仅仅须要准备一张图片就能够了。
我们终于要创建这种背景,如图:
背景是在滚动的,大家有没有看到?(小若:看你妹,这是jpg,不是gif)
大家是不是非常在意以下的那多出来的一条锯齿?它可不是坐标错位了,这是一个伏笔(还伏笔,你以为写小说啊。)。
本篇教程会用到的图片资源到这里下载:http://download.csdn.net/detail/musicvs/7392931
创建2张连续的背景图片
要实现循环滚动的背景,须要2张同样的图片实现,图片首尾相接。
我们要创建一个新的类。叫做BackgroundLayer,用来实现滚动背景。
创建2张同样的背景图片,非常easy,代码例如以下:
- Size visibleSize = Director::getInstance()->getVisibleSize();
- /* 背景图片 */
- m_bg1 = Sprite::create("background.jpg");
- m_bg1->setPosition(Point(visibleSize.width * 0.5f, visibleSize.height * 0.5f));
- this->addChild(m_bg1);
- m_bg2 = Sprite::create("background.jpg");
- m_bg2->setPosition(Point(visibleSize.width * 0.5f, -visibleSize.height * 0.5f));
- this->addChild(m_bg2);
- m_bg1和m_bg2都是Sprite对象。由于后面要用到。所以直接作为类的成员属性,方便调用。
m_bg1是屏幕居中。m_bg2要紧接着m_bg1的以下,大家感受一下。
创建边缘锯齿
先跑一下题,我们把边缘锯齿也给加入好:
- /* 创建边缘锯齿 */
- auto border = Sprite::create("border.png");
- Size borderSize = border->getContentSize();
- auto border1 = createBorder(Point(borderSize.width * 0.5f, borderSize.height * 0.5f));
- this->addChild(border1);
- auto border2 = createBorder(Point(visibleSize.width - borderSize.width * 0.5f, borderSize.height * 0.5f));
- border2->setFlippedX(true);
- this->addChild(border2);
- auto border3 = createBorder(Point(visibleSize.width * 0.5f, visibleSize.height * 0.15f));
- borderSize = border3->getContentSize();
- border3->setRotation(90.0f);
- this->addChild(border3);
- 一共三个锯齿,左右各一个。下方一个。
createBorder是自己定义函数,代码例如以下:
- Sprite* BackgroundLayer::createBorder(Point pos)
- {
- auto border = Sprite::create("border.png");
- Size borderSize = border->getContentSize();
- auto body = PhysicsBody::createBox(borderSize);
- body->setDynamic(false);
- body->setCategoryBitmask(1); // 0001
- body->setCollisionBitmask(1); // 0001
- body->setContactTestBitmask(1); // 0001
- border->setPhysicsBody(body);
- border->setPosition(pos);
- return border;
- }
- 好,这个函数要略微解释一下。这里使用PhysicsBody的createBox函数创建实体盒子刚体。由于边缘不是空心的。
然后调用了setDynamic函数,让刚体成为静态物体,也就是说。物理世界不会对它起产生影响了,它不会被撞飞。随你怎么撞,它都纹丝不动~
可是,它会对其它物理对象产生影响。比方有人撞了它,那个人就可能会反弹~
接着,有三个非常特别的函数:setCategoryBitmask、setCollisionBitmask、setContactTestBitmask。
这三个函数是用于物体间的碰撞检測的,用来作为推断条件,要解释它们须要不小的篇幅,所以我就不解释了(小若:有没有墙?我想撞一下)。
本游戏在碰撞检測方面极其简单,所以不理解这三个函数都全然没有影响。由于游戏里的全部对象都能产生碰撞,没有什么特别的地方。
假设以后有机会。我再单独写一篇文章来介绍吧(或者大家百度一下)
眼下的代码
好,来看看眼下为止BackgroundLayer的代码,头文件例如以下:
- #ifndef BackgroundLayer_H
- #define BackgroundLayer_H
- #include "cocos2d.h"
- USING_NS_CC;
- class BackgroundLayer : public Layer
- {
- public:
- BackgroundLayer();
- ~BackgroundLayer();
- CREATE_FUNC(BackgroundLayer);
- virtual bool init();
- private:
- Sprite* m_bg1;
- Sprite* m_bg2;
- Sprite* createBorder(Point pos);
- };
- #endif
- Cpp文件例如以下:
- #include "BackgroundLayer.h"
- BackgroundLayer::BackgroundLayer(){}
- BackgroundLayer::~BackgroundLayer(){}
- bool BackgroundLayer::init()
- {
- if (!Layer::init())
- {
- return false;
- }
- Size visibleSize = Director::getInstance()->getVisibleSize();
- /* 背景图片 */
- m_bg1 = Sprite::create("background.jpg");
- m_bg1->setPosition(Point(visibleSize.width * 0.5f, visibleSize.height * 0.5f));
- this->addChild(m_bg1);
- m_bg2 = Sprite::create("background.jpg");
- m_bg2->setPosition(Point(visibleSize.width * 0.5f, -visibleSize.height * 0.5f));
- this->addChild(m_bg2);
- /* 创建边缘锯齿 */
- auto border = Sprite::create("border.png");
- Size borderSize = border->getContentSize();
- auto border1 = createBorder(Point(borderSize.width * 0.5f, borderSize.height * 0.5f));
- this->addChild(border1);
- auto border2 = createBorder(Point(visibleSize.width - borderSize.width * 0.5f, borderSize.height * 0.5f));
- border2->setFlippedX(true);
- this->addChild(border2);
- auto border3 = createBorder(Point(visibleSize.width * 0.5f, visibleSize.height * 0.15f));
- borderSize = border3->getContentSize();
- border3->setRotation(90.0f);
- this->addChild(border3);
- return true;
- }
- Sprite* BackgroundLayer::createBorder(Point pos)
- {
- auto border = Sprite::create("border.png");
- Size borderSize = border->getContentSize();
- auto body = PhysicsBody::createBox(borderSize);
- body->setDynamic(false);
- body->setCategoryBitmask(1); // 0001
- body->setCollisionBitmask(1); // 0001
- body->setContactTestBitmask(1); // 0001
- border->setPhysicsBody(body);
- border->setPosition(pos);
- return border;
- }
- 先測试一下
我们来先測试一下代码的执行情况吧,我们给TollgateScene加入BackgroundLayer层,改动一下TollgateScene的scene函数:
- Scene* TollgateScene::scene()
- {
- auto scene = Scene::createWithPhysics();
- /* 这里省略了非常多代码 */
- /* 背景层 */
- auto backgroundLayer = BackgroundLayer::create();
- scene->addChild(backgroundLayer, 0);
- auto layer = TollgateScene::create();
- scene->addChild(layer, 10);
- return scene;
- }
OK。这样就能够了。再次执行代码,正常情况下,如图所看到的:
(小若:这就是一開始的那张图吧?连图片地址都一样好吧)
如今地图是不会滚动的,没意思,我们来開始滚床单…不,不好意思。习惯了(邪恶)。是滚动背景才对。
统一控制游戏逻辑
地图滚动,事实上就是不断改变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函数:
- class TollgateScene : public Layer
- {
- public:
- ~TollgateScene();
- static Scene* scene();
- CREATE_FUNC(TollgateScene);
- virtual bool init();
- virtual void onExit() override;
- private:
- void logic(float dt);
- BackgroundLayer* m_backgroundLayer;
- };
- #endif
以及我偷偷加入了一个BackgroundLayer成员变量,大实用处,不要着急~
然后改动一下TollgateScene的scene函数:
- Scene* TollgateScene::scene()
- {
- auto scene = Scene::createWithPhysics();
- /* 这里省略了非常多代码 */
- /* 背景层 */
- auto backgroundLayer = BackgroundLayer::create();
- scene->addChild(backgroundLayer, 0);
- auto layer = TollgateScene::create();
- scene->addChild(layer, 10);
- layer->m_backgroundLayer = backgroundLayer;
- return scene;
- }
留意最后一句代码(小若:是倒数第二句!
)。好吧。倒数第二句,我们保留了BackgroundLayer的引用。也许这样保持引用是比較糟糕的做法,也许用getChildByTag的方式来获取BackgroundLayer会好一些,但由于这对象要使用非常多次,我选择了直接保存引用。
大家依据个人喜好来决定吧~
OK,最重要的,看看TollgateScene的logic函数实现。有点复杂,大家要有心理准备:
- void TollgateScene::logic(float dt)
- {
- m_backgroundLayer->logic(dt);
- }
(小若:= =哇,好复杂啊,全然看不懂….(蛇精病))
我想,大家已经理解我之前说的,统一控制逻辑的意思了吧?由TollgateScene场景来调用各个层的logic函数。这样非常方便。要停止逻辑的时候,仅仅要由TollgateScene控制一下就能够了,不须要对各个层单独地进行控制。
OK,别忘了。在TollgateScene的init函数加上schedule的调用:
- bool TollgateScene::init()
- {
- if (!Layer::init())
- {
- return false;
- }
- this->schedule(schedule_selector(TollgateScene::logic));
- return true;
- }
BackgroundLayer背景层的逻辑
好了,我们还得为BackgroundLayer加入一个logic逻辑处理函数,头文件加入函数声明:
- class BackgroundLayer : public Layer
- {
- public:
- BackgroundLayer();
- ~BackgroundLayer();
- CREATE_FUNC(BackgroundLayer);
- virtual bool init();
- void logic(float dt);
- private:
- Sprite* m_bg1;
- Sprite* m_bg2;
- Sprite* createBorder(Point pos);
- };
BackgroundLayer的logic函数实现例如以下,这个就真的有点小复杂了:
- void BackgroundLayer::logic(float dt) {
- int posY1 = m_bg1->getPositionY(); // 背景地图1的Y坐标
- int posY2 = m_bg2->getPositionY(); // 背景地图2的Y坐标
- int iSpeed = 3; // 地图滚动速度
- /* 两张地图向上滚动(两张地图是相邻的,所以要一起滚动。否则会出现空隙) */
- posY1 += iSpeed;
- posY2 += iSpeed;
- /* 屏幕宽 */
- int iVisibleHeight = Director::getInstance()->getVisibleSize().height;
- /* 当第1个地图全然离开屏幕时,让第2个地图全然出如今屏幕上。同一时候让第1个地图紧贴在第2个地图后面 */
- if (posY1 > iVisibleHeight * 1.5f) {
- posY2 = iVisibleHeight * 0.5f;
- posY1 = -iVisibleHeight * 0.5f;
- }
- /* 同理。当第2个地图全然离开屏幕时,让第1个地图全然出如今屏幕上。同一时候让第2个地图紧贴在第1个地图后面 */
- if (posY2 > iVisibleHeight * 1.5f) {
- posY1 = iVisibleHeight * 0.5f;
- posY2 = -iVisibleHeight * 0.5f;
- }
- m_bg1->setPositionY(posY1);
- m_bg2->setPositionY(posY2);
- }
原理我就不解释了。大家看看代码凝视。然后自己在纸上画一画,非常好理解的。反正目的就是让两张背景不断往上移动。一旦图片全然离开屏幕,就让它回到屏幕下方,然后又继续往上移动。
好了,如今执行游戏,就能看到背景在滚动了~
OK。接下来,我们已正式加入了主角。
版权声明:本文博主原创文章,博客,未经同意不得转载。
Cocos2d-x3.0游戏实例《不要救我》三——背景滚动周期的更多相关文章
- Cocos2d-x3.0游戏实例《不要救我》第十篇(结束)——使用Json配置数据类型的怪物
如今我们有2种类型的怪物,并且创建的时候是写死在代码里的,这是要作死的节奏~ 所以.必须可配置.不然会累死人的. ; i < size; ++i) { int id = root[i][&quo ...
- Cocos2d-x3.0游戏实例《不要救我》第一章——前言
我们可以学习? 这是一个非常easy游戏.但更多的东西用(对于初学者).至少,对于它的一个例子,有点多. 笨木头花心贡献.啥?花心?不呢.是用心~ 转载请注明,原文地址:http://www.benm ...
- Cocos2d-x3.0游戏实例之《别救我》第八篇——TiledMap实现关卡编辑器
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/musicvs/article/details/25368273 好吧.我真心全然搞不懂.我如今仅仅只 ...
- 《MFC游戏开发》笔记七 游戏特效的实现(一):背景滚动
本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9344721 作者:七十一雾央 新浪微博:http:// ...
- Cocos2d-x3.0游戏实例之《别救我》第六篇——从代码中获取UI控件
这篇的内容非常easy,获取UI控件,然后使用它. 还记得我们在UI编辑器中给三个button分别命名了吧? 如今要用上了. 笨木头花心贡献,啥?花心?不呢,是用心~ 转载请注明,原文地址: http ...
- Cocos2d-x3.0游戏实例之《别救我》第二篇——创建物理世界
这篇我要给大家介绍两个知识点: 1. 创建游戏物理世界 2. 没了(小若:我噗) 害怕了?不用操心.这太简单了~! 笨木头花心贡献.啥?花心?不呢.是用心~ 转载请注明,原文地址:http://www ...
- Cocos2d-x3.0游戏实例之《别救我》第四篇——乱入的主角
好了,前面说了那么多废话,最终要进入正题了(等等,敢情前面你都是在耍我们么?) 笨木头花心贡献,啥?花心?不呢,是用心~ 转载请注明,原文地址: http://www.benmutou.com/blo ...
- Cocos2d-x3.0游戏实例之《别救我》第七篇——物理世界的碰撞检測
事实上我也非常吃惊-居然写到第七篇了,我估计也就是四篇的内容,感觉非常奇妙,我也不会非常唠叨什么吖); // 0001 ); // 0001 ); // 0001 这样我们才干监听到它们的碰 ...
- cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第二步---编辑器(1)--触摸加入点
/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦,他说:随便写,第一别全然照搬代码:第二能够说 ...
随机推荐
- 南阳OJ 16 矩形嵌套
描写叙述 有n个矩形,每个矩形能够用a,b来描写叙述,表示长和宽. 矩形X(a,b)能够嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度). ...
- 【C语言疯狂讲义】(八)C语言一维数组
1.数组的基本概念: 同样类型 若干个 有序 由若干个同样类型的数据组成的有序的集合 有序:存储地址连续 下标连续 数组名:用来存放数组首地址的变量 数组元素:构成数组的每个数据 数组的 ...
- Android动绘图标——I am not a gif maker,I am a developer
最早在git上发现一个非常酷眩的动绘图标效果: https://github.com/xuyisheng/tickplusdrawable 不得不说,国外的程序猿在细节的考虑上,确实比我们要好非常多, ...
- WPF案例 (五) 对控件界面使用倒影
原文:WPF案例 (五) 对控件界面使用倒影 在这个程序里对5个2D控件界面应用了垂直倒影,边缘模糊化和模型变换,在本例中,这5个2D控件为Border, 各包含了一幅Image,界面如下图所示,源码 ...
- POJ 1088 滑雪 记忆化优化题解
本题有人写是DP,只是和DP还是有点区别的,应该主要是记忆化 Momoization 算法. 思路就是递归,然后在递归的过程把计算的结果记录起来,以便后面使用. 非常经典的搜索题目,这样的方法非常多题 ...
- 2014ACM/ICPC亚洲区西安站 F题 color (组合数学,容斥原理)
题目链接:传送门 题意: n个格子排成一行.我们有m种颜色.能够给这些格子涂色,保证相邻的格子的颜色不同 问,最后恰好使用了k种颜色的方案数. 分析: 看完题目描写叙述之后立刻想到了一个公式 :C(m ...
- IntelliJ IDEA 14 注册码生成java代码(转)
https://confluence.jetbrains.com/display/IntelliJIDEA/Previous+IntelliJ+IDEA+Releases 分享几个license: ( ...
- iOS_16_开关控制器_modal_代码方法
最后效果图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcHJlX2VtaW5lbnQ=/font/5a6L5L2T/fontsize/400/fill ...
- 在mysql数据库中关于日期时间字段的处理
在mysql数据库中关于日期时间字段的处理 在开发中,日期时间字段一般有如下几种设计 假设要获取2013-08-15日到2013-08-16日之间的记录 1. 直接使用日期时间类字段 相关sql语句如 ...
- pygame系列_游戏窗口显示策略
在这篇blog中,我将给出一个demo演示: 当我们按下键盘的‘f’键的时候,演示的窗口会切换到全屏显示和默认显示两种显示模式 并且在后台我们可以看到相关的信息输出: 上面给出了一个简单的例子,当然在 ...