Cocos2d-x 实现地图滚动,解释缝隙产生的原因以及解决方案
温馨提示:如果只是找缝隙解决方案的请直接跳到最后的第4点。
在跑酷游戏(天天酷跑)或者射击游戏(打飞机)中都有背景循环移动的机制。网上也有很多的实现方法,我这里先直接用代码反映出来:
首先申明的是我这个是做的横版向左移动:
- /*
- HelloWorldScene.h
- */
- #ifndef __HELLOWORLD_SCENE_H__
- #define __HELLOWORLD_SCENE_H__
- #include "cocos2d.h"
- #define MAP_1_Tag 1 // 宏定义两个Map的Tag
- #define MAP_2_Tag 2
- class HelloWorld : public cocos2d::CCLayer
- {
- private:
- void update(float time);
- virtual void onExit();
- public:
- virtual bool init();
- static cocos2d::CCScene* scene();
- CREATE_FUNC(HelloWorld);
- };
- #endif
- /*
- HelloWorldScene.cpp
- */
- #include "HelloWorldScene.h"
- USING_NS_CC;
- CCScene* HelloWorld::scene()
- {
- CCScene *scene = CCScene::create();
- HelloWorld *layer = HelloWorld::create();
- scene->addChild(layer);
- return scene;
- }
- bool HelloWorld::init()
- {
- if ( !CCLayer::init() )
- {
- return false;
- }
- CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
- CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
- CCSprite* map1 = CCSprite::create("HelloWorld.png");
- CCSprite* map2 = CCSprite::create("HelloWorld.png");
- map1->setPosition(ccp(map1->getContentSize().width/2 + origin.x, map1->getContentSize().height/2 + origin.y));
- map2->setPosition(ccp(map2->getContentSize().width/2 + origin.x + map2->getContentSize().width, map2->getContentSize().height/2 + origin.y));
- this->addChild(map1, 0, MAP_1_Tag);
- this->addChild(map2, 0, MAP_2_Tag);
- this->scheduleUpdate();
- return true;
- }
- void HelloWorld::update(float time)
- {
- CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
- CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
- CCSprite* temMap1 = (CCSprite*)this->getChildByTag(MAP_1_Tag);
- CCSprite* temMap2 = (CCSprite*)this->getChildByTag(MAP_2_Tag);
- temMap1->setPositionX(temMap1->getPositionX() - 5);
- temMap2->setPositionX(temMap2->getPositionX() - 5);
- if(temMap1->getPositionX() + temMap1->getContentSize().width/2 <= origin.x)
- {
- float offset = temMap1->getPositionX() + temMap1->getContentSize().width/2 - origin.x;
- temMap1->setPosition(ccp(temMap1->getContentSize().width/2 + origin.x + visibleSize.width + offset, visibleSize.height/2 + origin.y));
- }
- if(temMap2->getPositionX() + temMap2->getContentSize().width/2 <= origin.x)
- {
- float offset = temMap2->getPositionX() + temMap2->getContentSize().width/2 - origin.x;
- temMap2->setPosition(ccp(temMap2->getContentSize().width/2 + origin.x + visibleSize.width + offset, visibleSize.height/2 + origin.y));
- }
- }
- void HelloWorld::onExit()
- {
- this->unscheduleUpdate();
- CCLayer::onExit();
- }
这里就提几点问题吧:
cocos2d-x学习记录-Tiled使用注意点
用Tiled新建 好地图后放到cocos2d上使用,
// 加载Tiled地图
CCTMXTiledMap *map = CCTMXTiledMap::create("birdMap.tmx");
this->addChild(map);
然后报如下错误
Assert failed: TMX: Only 1 tileset per layer is supported
原来是我把多个图块上的元素,都画到一个块层上,一个块层只能包含一个图块的元素,
新建不同块层安放其它图块元素,就解决了。
还有自己处理的图块文件,如 在导入时,
块宽度与块高度是最重要的,
如果自已处理的文件,不计算好这个像素的话,显示就会出问题,像这样
显示不全,那是因为我这张PNG图,尺寸是180 X 250, 但我导入块时的设置是 块宽度与高度都是32像素。
而Tiled都是按整数计算,而且无视四舍五入,直接去掉小数位,就是说 180÷32 = 5.625,它只会显示该
所以在自作地图素材时,要想好自己要以怎样的块宽度和高度导入,然后到PS里, 先用辅助线,拉好相
类
所有实例化Cocos2d-x里面的以CCObject为基类的类时,都要使用其create()方法来创建对象,对于自己添加的派生类,需要通过CREATE_FUNC宏来实现create()方法,下面以《如何制作一个横版格斗过关游戏 Cocos2d-x 2.0.4》来举例介绍:
Hero.h
1
2 3 4 5 6 7 8 9 |
class Hero : public ActionSprite
{ public: Hero(void); ~Hero(void); CREATE_FUNC(Hero); |
若是需要create()方法带有参数的话,仿造CREATE_FUNC的定义来实现,CREATE_FUNC宏定义如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#define CREATE_FUNC(__TYPE__) \
static __TYPE__* create() \ { \ __TYPE__ *pRet = new __TYPE__(); \ if (pRet && pRet->init()) \ { \ pRet->autorelease(); \ return pRet; \ } \ else \ { \ delete pRet; \ pRet = NULL; \ return NULL; \ } \ } |
具体可以类似如下:
SimpleDPad.h
1
2 3 4 5 6 7 8 9 10 |
class SimpleDPad : public cocos2d::CCSprite, public cocos2d::CCTargetedTouchDelegate
{ public: SimpleDPad(void); ~SimpleDPad(void); static SimpleDPad* dPadWithFile(cocos2d::CCString *fileName, float radius); |
其中dPadWithFile静态方法就是仿造的create()方法,具体实现如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
SimpleDPad* SimpleDPad::dPadWithFile(CCString *fileName, float radius)
{ SimpleDPad *pRet = new SimpleDPad(); if (pRet && pRet->initWithFile(fileName, radius)) { pRet->autorelease(); return pRet; } else { delete pRet; pRet = NULL; return NULL; } } |
当然这里的方法名可以改为以create开头方便统一。
变量
当create出来的变量,被addChild到以CCNode为基类的类时,或者被addObject到CCArray、CCSet等时,都会自动将这个变量对象retain()一次,以防止被自动释放导致的野指针问题,所以一般情况都不需要再手动调用retain()方法了。对于类定义中用CC_SYNTHESIZE_RETAIN宏声明的变量,或者对临时变量手动调用了retain()方法,一般都需要在析构函数或者特定的函数进行手动调用release()方法,类似如下:
GameLayer.h
1
2 3 4 5 6 7 8 9 10 |
class GameLayer : public cocos2d::CCLayer, public SimpleDPadDelegate
{ public: GameLayer(void); ~GameLayer(void); CREATE_FUNC(GameLayer); |
GameLayer.cpp
1
2 3 4 5 6 7 8 9 10 11 |
GameLayer::GameLayer(void)
{ //…… _robots = NULL; } GameLayer::~GameLayer(void) |
但是有一种特殊情况,类与变量的互相retain(),导致无法释放,内存泄露。
ActionSprite.h
1
2 3 4 5 6 7 8 9 |
class ActionSprite : public cocos2d::CCSprite
{ public: ActionSprite(void); ~ActionSprite(void); //…… |
Hero.cpp
1
2 3 4 5 6 7 8 9 10 11 12 13 |
bool Hero::init()
{ bool bRet = false; do { //…… this->setAttackAction(CCSequence::create(CCAnimate::create(attackAnimation), CCCallFunc::create(this, callfunc_selector(Hero::idle)), NULL)); //…… return bRet; |
_attackAction变量以CCSequence类创建,CCSequence创建包含CCCallFunc的创建,CCCallFunc创建的时候将this指针传递下去,跟踪源码:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
CCCallFunc * CCCallFunc::create(CCObject* pSelectorTarget, SEL_CallFunc selector)
{ CCCallFunc *pRet = new CCCallFunc(); if (pRet && pRet->initWithTarget(pSelectorTarget)) { CC_SAFE_DELETE(pRet); bool CCCallFunc::initWithTarget(CCObject* pSelectorTarget) { if (m_pSelectorTarget) m_pSelectorTarget = pSelectorTarget; |
可以看到它对this指针的对象进行retain()调用,导致Hero对象无法被自动释放,需要先手动对_attackAction变量进行release()调用,CCCallFunc将进行析构,进而将会对this指针的对象进行release()调用
1
2 3 4 |
virtual ~CCCallFunc()
{ CC_SAFE_RELEASE(m_pSelectorTarget); } |
解决方法举例如下:
ActionSprite.h
1
2 3 4 5 6 |
class ActionSprite : public cocos2d::CCSprite
{ public: //…… virtual void cleanup(); }; |
ActionSprite.cpp
1
2 3 4 5 6 7 8 |
void ActionSprite::cleanup()
{ CC_SAFE_RELEASE_NULL(_idleAction); CC_SAFE_RELEASE_NULL(_attackAction); CC_SAFE_RELEASE_NULL(_walkAction); CC_SAFE_RELEASE_NULL(_hurtAction); CC_SAFE_RELEASE_NULL(_knockedOutAction); CCSprite::cleanup(); |
最后用Visual Leak Detector和DevPartner检测,均未检测到内存泄露。
如文章存在错误之处,欢迎指出,以便改正。By 无
Cocos2d-x 实现地图滚动,解释缝隙产生的原因以及解决方案相关推荐
- cocos植物大战僵尸(三)游戏场景:地图滚动
2.3游戏场景 2.3.1 地图滚动 根据json表读取出,当前关卡要载入哪张地图,并读取当前地图的相关.Json表为数组结构,配置如下: [{"Level":0,"Ma ...
- 【Cocos2D-X 游戏引擎】初窥门径(7)无限地图滚动
地图的滚动原理很简单,就是持续设置地图的位置即可.具体实现用schedule()函数. pMap = CCSprite::create("MapHenn.png");pMap-&g ...
- 游戏编程基础(五)背景地图滚动显示
在游戏过程中,背景地图需要跟着人物的移动而动态的滚动变换.C++游戏编程基础中介绍了2D游戏中常用的3种动态背景表现手法.其原理和实现技巧分析如下: 方法一:单一背景滚动 原理是:利用 ...
- Cocos2d:使用 CCCamera 做滚动效果 (Four Ways of Scrolling with Cocos2D)
原版的:http://www.koboldtouch.com/display/IDCAR/Four+Ways+of+Scrolling+with+Cocos2D There are two class ...
- UNITY2D 地图滚动DEMO
UNITY 2D开发,对地图划分为21x21=441块,改变每一块的图片加载,达到显示地图对象的目的. 不好意思,这是一种非常笨的办法... 核心代码: using System.Collection ...
- 百度地图——判断用户是否在配送范围内解决方案
需求: 在pc端设置商家的配送范围,用户在下单时,根据用户设置的配送地点判断是否在可配送范围内,并给用户相应的提示. 实现: 1.用百度地图在PC端设置配送范围,可拖拽选择 2.根据用户设置的配送地址 ...
- Vue 移动端项目 百度地图 点击事件无效、不触发 解决方案
解决百度地图 手机端 点击事件不触发 的一种方案 版权声明:本文为博主原创文章,转载请标明原文出处. 问题背景 我是半路接手的这个项目,该项目使用 Vue 开发的一款 手机端的页面.到手里时,使用百 ...
- 百度卫星地图无法使用鼠标绘制工具的问题简单解决方案
问题 最近手上的一个有关百度地图的bug 具体是这样的: 在街道地图和自定义地图上是没问题的,可以框选提交 在地球模式下,没有√×选项,没法提交 解决过程 首先,我觉得应该不是代码的问题,于是提了相关 ...
- 地图大量数据查询与渲染——bug及解决方案
本文记录大数据可视化项目中信息查询过程遇到的实际问题及解决方案,用到了Vue自定义组件.Promise.all.DocumentFragment.event loop等. 项目需求 项目使用的arcg ...
最新文章
- oracle双机切换 无法挂载,Linux下Oracle RAC一个节点宕机导致共享存储无法挂载的故障排除...
- 5、Makefile基础知识汇总(转自陈皓总述)
- heartbeat+drbd+mysql:实现最廉价的高可用组合
- python时间模块哪个好arrow模块_python库: arrow (时间)
- java list 转 map_Java8 快速实现List转map 、分组、过滤等操作
- Linux i2c子系统驱动probe
- python 安装中的错误解决
- Android Gradle实用技巧——APK文件名中加上SVN版本号,日期等
- SQLyog客户端常用快捷键
- Xcode 7.3 解决自定义类无法自动联想
- WPS EXCEL 处理字符串转换为日期格式
- Android--BRVAH官方使用指南
- 人工智能7大关键技术,终于有人讲明白了
- marlin固件烧录教程_marlin固件中文(marlin固件下载)
- 第二十四题——[ZJCTF 2019]NiZhuanSiWei
- 概率论复习笔记二——离散型分布和连续型分布
- 数据库子查询-select后面语句
- word段落居中的快捷键_Word段落设置中的小技巧和快捷键推荐
- 学生成绩计算的c语言,学生成绩标准管理系统C语言.doc
- 归因分析计算因子贡献度常见的方法
热门文章
- Tyrion 中文文档(含示例源码)
- 中国31省 5G网速 排名!
- 为什么转置512x512矩阵,会比513x513矩阵慢很多?
- CSS - 使表格td中的文字垂直居中
- Android---简易的底部导航栏
- 单例模式java概括_单例模式中总有几个歪门邪道的问题要知道!
- 基于SpringBoot调用百度ocr以及企查查接口实现对营业执照信息的提取并识别真伪
- 优美的数列(斐波那契数列)
- 万国觉醒服务器维护,万国觉醒好像没看到1服怎么回事 官方关闭部分服务器公告[多图]...
- 学mei私聊问我【DISTINCT】关键字有什么作用?查一个字段和多个字段的区别?