cocos2d-x中的Tiled地图
cocos2d-x中的瓦片地图是通过tiledMap软件制作的,存档格式是.tmx格式。此软件的使用步骤简单总结如下:
(1)制作瓦片地图
1 打开软件,软件界面如下图。
2. 新建地图(文件->新文件)
3.增加新图块(地图->新图块)
4. 制作地图。在图层区域,单击右键可以新建图层和对象,上面的工具栏中的工具,制作地图。
5 导出,记住格式一定是tmx格式
说明
- 有时候,在使用地图的时候,可能会报找不到资源的错误,可以使用xcode打开地图文件,将资源路径修改如图所示形式。
在地图完成后,我们接下来要做的是读取tmx文件并操作文件实现我们想要的效果
(2)读取地图文件的内容
1. CCTMXTiledMap类
这个类是cocos2d-x专门设计用来读取和解析TMX文件的。CCTMCTiledMap类继承自CCNode类,我们通过调用static CCTMXTiledMap * create(const char *tmxFile)和static CCTMXTiledMap * create(const char *tmxFile,const char *resourcePath)方法就可以创建CCTMXTiledMap的对象,然后我们调用addChild();就可以将地图加入到层中
CCTMXTiledMap有以下特点:
- 每个砖块元素都被当作精灵对象来处理。
- 每个地图中的砖块,只有在需要的时候才会被创建,只有在开发者调用类CCLayer的tileAt之后,对象才会创建。
- 每个砖块都支持旋转、移动、伸缩、变色以及透明度。
- 开发者可以删除或者添加砖块元素。
- 砖块的z轴,也是可以修改地。
- 每个地图对象存在锚点,默认为(0,0)。
- 每个TMX中的图层都会成为地图地子节点。
- 每个砖块元素都有一个唯一的标志数值。
- 仅支持XML格式,不支持Json格式。
CCTMXTiledMap比较常用的成员函数:
获得和设置地图的尺寸
l const CCSize & getMapSize(void);
l void setMapSize(const CCSize &var)
获得和设置砖块的尺寸
l const CCSize & getileSize(void);
l void setTileSize(cosnt CCSize &var);
获得和设置地图的方向
l const int getMapOrientation();
l void setMapOrientation(int var);
设置和获得对象数组
l CCArray * getObjectGroups();
l Void setObjectGroups(CCArray *var);
获得和设置地图地属性
l void setProperties(CCDictionary *var);
l CCDictionary * getProperties(void);
/* 初始化方法(常用)*/
static CCTMXTiledMap* create(const char *tmxFile);
/** 通过名字获得地图中的层*/
CCTMXLayer* layerNamed(const char *layerName);
/** TMXObjectGroup 对象组,获得一个名字下的对象组*/
CCTMXObjectGroup* objectGroupNamed(const char *groupName);
/** 获得一个属性的值 */
CCString *propertyNamed(const char *propertyName);
/**获得地图中某个图块的所有对象(注意一个图块可能有多个对象) */
CCDictionary* propertiesForGID(int GID);
2. CCTMXLayer类(地图图层类)
//获得和设置图层尺寸的大小
virtual const CCSize & getLayerSize(void);
virtual void setLayerSize(const CCSize &var);
//获得和设置砖块尺寸
virtual const CCSize & getMapTileSize(void);
virtual void setMapTileSize(const CCSize &var);
//获得和设置砖块的属性
virtual CCTMXTilesetInfo * getTileSet(void);
virtual void setTileSet(CCTMXTilesetInfo *var);
//获得和设置图层属性字典
virtual CCDictionary *getProperties(void);
virtual void setProperties(CCDictionary *var);
//返回指定位置的砖块对象
CCSprite *tileAt(const CCPoint &tileCoordinate);
//返回指定位置的砖块的对象的ID
unsigned int tileGIDAt(const CCPoint &tileCoordinate);
//移除指定位置的砖块对象
void removeTileAt(const CCPoint& tileCoordinate);
//获得和设置图层名字
inline const char* getLayerName();
inline void setLayerName(const char *layerName);
3. CCTMXObjectGroup类(地图物体层(对象层))
//获得物体层的属性字典
virtual CCDictionary * getProperties(void);
//设置物体层的属性字典
virtual void setProperties(CCDictionary *var);
//获得物体层中的物体对象
virtual CCArray * getObjects(void);
//设置物体层中的物体对象
virtual void setObjects(CCArray *var);
//返回物体层的名字
inline const char* getGroupName();
//设置物体层的名字
inline void setGroupName(const char *groupName);
//获得指定属性的数值
CCString *propertyNamed(const char* propertyName);
//根据属性名字,返回属性字典
CCDictionary* objectNamed(const char *objectName);
(3)下面是对瓦片地图练习的Demo
1. 制作的地图如下:
2. 代码关联地图
1>加载地图并读取地图上得层
bool HelloWorld::init()
{
if ( !CCLayer::init() )
{
return false;
} // 将按钮添加到场景中,避免按钮随地图运动
btnMenu = ButtonMenu::create();
sc->addChild(btnMenu, 5); //加载地图
_tileMap = CCTMXTiledMap::create("myMap.tmx");
addChild(_tileMap); //添加英雄
addHero(); //添加层的触摸
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 1, false); //获取地图中的不能行走的层(墙等障碍物)
_meta = _tileMap->layerNamed("meta"); //使不能行走区隐藏起来
_meta->setVisible(false); //获取地图上的西瓜层
_fruit = _tileMap->layerNamed("Fruit"); //记得数组要retain一下。
_enemyArray = CCArray::create();
_enemyArray->retain(); //初始化存放子弹的数组
_bulletArray = CCArray::create();
_bulletArray->retain(); //添加敌人
addEnemy(); //碰撞检测
this->schedule(schedule_selector(HelloWorld::updataGame), 0.1); return true;
}
<2> 添加玩家精灵
void HelloWorld::addHero()
{
//获取对象图层hero中的对象组
CCTMXObjectGroup *objectsValue = _tileMap->objectGroupNamed("hero"); //获取地图上的设置好的英雄对象的信息
CCDictionary *spawnPoint = objectsValue->objectNamed("pa"); _player = CCSprite::create("www.png");
_player->setAnchorPoint(ccp(0, 0)); //根据地图上设置好的英雄位置来设置当前精灵的位置
_player->setPosition(ccp(spawnPoint->valueForKey("x")->floatValue(), spawnPoint->valueForKey("y")->floatValue()));
addChild(_player);
}
<3>添加敌人精灵和人物行走动作
void HelloWorld::addEnemy()
{
//获取对象图层hero中的对象组
CCTMXObjectGroup *objectsValue = _tileMap->objectGroupNamed("hero"); //添加敌人, 非快速遍历
for(int i = 0; i < int(objectsValue->getObjects()->count()); ++i)
{
//获取地图中对应的元素
CCDictionary *element = (CCDictionary *)objectsValue->getObjects()->objectAtIndex(i); //如果找到敌人对象,把精灵放到地图上显示出来
if (element->valueForKey("n")->intValue() == 1) { //初始化敌人精灵,把地图中已经初始化好的敌人对象初始化为要用的敌人精灵。
CCSprite *enemySprite = CCSprite::create("enemy1.png");
float x = element->valueForKey("x")->floatValue();
float y = element->valueForKey("y")->floatValue();
enemySprite->setPosition(ccp(x, y));
enemySprite->setAnchorPoint(ccp(0, 0));
_tileMap->addChild(enemySprite, 4);
_enemyArray->addObject(enemySprite); //让敌人向英雄运动。
CCCallFuncN *func = CCCallFuncN::create(this, callfuncN_selector(HelloWorld::goon));
enemySprite->runAction(func);
}
}
} void HelloWorld::goon(CCNode *pSender)
{
//获取敌人精灵
CCSprite *s = (CCSprite *)pSender; //x轴方向移动的距离,画图理解
float x = _player->getPosition().x - s->getPosition().x > 0 ? 10 : -10; //y轴方向上移动的距离
float y = _player->getPosition().y - s->getPosition().y > 0 ? 10 : -10; CCMoveBy *move = CCMoveBy::create(0.5, ccp(x, y)); //递归调用,让敌人精灵向英移动
CCCallFuncN *func = CCCallFuncN::create(this, callfuncN_selector(HelloWorld::goon)); s->runAction(CCSequence::create(move, func, NULL)); }
<4>检测碰撞
void HelloWorld::updataGame()
{
//数组的快速遍历
CCObject* obj = NULL;
CCARRAY_FOREACH(_enemyArray, obj)
{
//强制类型转换
CCSprite *s = static_cast<CCSprite *>(obj); if(_player->boundingBox().intersectsRect(s->boundingBox()))
{
//如果英雄与敌人发生碰撞就结束游戏回到主场景。
CCDirector::sharedDirector()->replaceScene(MainLayer::scene());
}
} CCARRAY_FOREACH(_bulletArray, obj)
{
CCSprite *bullet = (CCSprite *)obj; CCARRAY_FOREACH(_enemyArray, obj)
{
CCSprite *enemy = (CCSprite *)obj; //如果子弹与敌人发生碰撞
if(bullet->boundingBox().intersectsRect(enemy->boundingBox()))
{
//把子弹和敌人从地图中移除
enemy->removeFromParent();
bullet->removeFromParent(); _enemyArray->removeObject(enemy);
_bulletArray->removeObject(bullet); //子弹移除之后就跳出当前的循环
break;
}
}
}
}
<5>获得触摸点并操作人物
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
//获取当前触摸到的点的位置
CCPoint point = pTouch->getLocation(); //将openGL坐标系转化为结点做标系,可以定位到节点真实(距离地图最左边的位置而不是距离屏幕左下角的位置)的位置
_beginPoint = convertToNodeSpace(point); return true;
} void HelloWorld::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
//获取当前用户的点击结束点
CCPoint point = pTouch->getLocation(); CCPoint endPoint = convertToNodeSpace(point); if(!(btnMenu->isbullet)) { //如果开始与结束点是同一个点,保证是点击而不是手指滑动
if(_beginPoint.equals(endPoint))
{
//获取精灵原来的位置
CCPoint playerPos = _player->getPosition(); //得到用户触摸点与原来精灵点的位置的差距
CCPoint disPos = endPoint - playerPos; //判断偏移的距离是偏上下,还是偏左右。画图理解很容易
//偏左右
if(abs(disPos.x) >= abs(disPos.y))
{
if(disPos.x > 0)
{
//每次偏移一个图块的宽度。
playerPos.x += _tileMap->getTileSize().width;
}
else
{
playerPos.x -= _tileMap->getTileSize().width;
}
}
else //偏上下
{
if(disPos.y > 0)
{
//每次偏移一个图块的高度
playerPos.y += _tileMap->getTileSize().height;
}
else
{
playerPos.y -= _tileMap->getTileSize().height;
}
}
movePlayer(playerPos); //地图随精灵移动
setViewpointCenter(_player->getPosition());
}
} else {
//发射飞镖
CCSprite *bullet = CCSprite::create("Projectile.png");
bullet->setPosition(_player->getPosition());
_tileMap->addChild(bullet, 4);
_bulletArray->addObject(bullet); //当前手触摸点与英雄精灵x轴上的差值
float dx = endPoint.x - _player->getPosition().x;
//当前手触摸点与英雄精灵y轴上的差值
float dy = endPoint.y - _player->getPosition().y; //子弹向x, y方向移动的坐标点
float lx, ly; //向前发子弹
if(dx > 0)
{
//画图看一下就明白为什么是这样了。winSize是指右边屏幕的边界。
lx = _tileMap->getTileSize().width * _tileMap->getMapSize().width - _player->getPosition().x;
//ly / lx = dy / dx;
ly = dy / dx * lx;
} else {
lx = 0 - _player->getPosition().x;
ly = dy / dx * lx;
} CCMoveBy *move = CCMoveBy::create(2, ccp(lx, ly));
//子弹发射完毕之后执行回收子弹的函数。
CCCallFuncN *ff = CCCallFuncN::create(this, callfuncN_selector(HelloWorld::targetFinish)); bullet->runAction(CCSequence::create(move, ff, NULL));
} }
<6>地图随人物的移动而发生移动
void HelloWorld::setViewpointCenter(CCPoint position)
{
//获取当前屏幕的尺寸
CCSize winSize = CCDirector::sharedDirector()->getWinSize(); //如果精灵在屏幕中央的左边或者右边,x的值就是精灵当前的x值,否则x的值就是屏幕宽度的一半。
int x = MAX(position.x, winSize.width / 2); //获取整个地图的尺寸
CCSize mapSize = _tileMap->getMapSize(); //获取每一个图块的宽高
CCSize tileSize = _tileMap->getTileSize(); CCLOG("%lf, %lf, %lf, %lf", mapSize.width, mapSize.height, tileSize.width, tileSize.height); //mapSize.width是地图的x轴方向上有多少个瓦片,当前是30
//mapSize.height是地图的y轴方向上有多少个瓦片,当前是10 //重新规划x的值。
x = MIN(x, mapSize.width * tileSize.width - winSize.width / 2); //获取屏幕中心点的位置
CCPoint centerPoint = CCPoint(winSize.width / 2, winSize.height / 2); //重新规划的位置
CCPoint actualPoint = CCPoint(x, winSize.height / 2); //地图最终要移动到的位置
CCPoint viewPoint = centerPoint - actualPoint; //重新规划当前视图的位置。
this->setPosition(viewPoint);
}
<7> 玩家与障碍物间的移动控制
void HelloWorld::movePlayer(CCPoint p)
{
//map->getMapSize():地图的图块数 //map->getTileSize():每一个图块的宽高 //获取目标的位置,就是当前在哪个图块上
int x = p.x / _tileMap->getTileSize().width;//定位在x轴的第几块上
int y = _tileMap->getMapSize().height - (p.y / _tileMap->getTileSize().height);//定位在y轴的第几块上 //得到当前的定位点
CCPoint currentPoint = ccp(x, y); //判断是否在地图范围内
if(x != _tileMap->getMapSize().width && y != _tileMap->getMapSize().height) { //是否获取到目标,根据指定的点获取到图块中小图块的id.比如遇到障碍物id是49,遇到西瓜id是50。(map图块中有48块),(meta图块中有2块),红色的是第一块48+1= 49,绿色的是第二块48+2=50;
int tilegId = _meta->tileGIDAt(currentPoint); //如果瓦片存在
if(tilegId){ //Dictionary;根据图块id获取当前图块上的各个属性
CCDictionary *properties = _tileMap->propertiesForGID(tilegId);
CCString *metaStr = (CCString *)properties->objectForKey("barrier");
CCString *fruitStr = (CCString *)properties->objectForKey("watermelon");
//如果是遇到了障碍物,且不是西瓜,就不让精灵移动
if (metaStr && metaStr->compare("red") == 0) {
CCLog("+++++++++++++++\n");
return;
} else if (fruitStr && fruitStr->compare("green") == 0) {
_meta->removeTileAt(currentPoint); //获得当前的水果,并将其从视图中移除。
CCSprite *fruitSprite = _fruit->tileAt(currentPoint);
fruitSprite->removeFromParent();
}
} //让英雄移到到点击的瓦片上
_player->setPosition(p);
}
}
<8> 移除精灵
//当飞镖到达边界时移除飞镖
void HelloWorld::targetFinish(CCNode *pSender)
{
pSender->removeFromParent();
_bulletArray->removeObject(pSender);
}
cocos2d-x中的Tiled地图的更多相关文章
- Cocos2d-x Tiled地图编辑器(一)基本使用
Tiled地图编辑器支持普通视角地图和45度角地图, 它生成的地图数据文件cocos2d-x完美的支持,Tiled地图编辑器是一个以普通使用为目标地图编辑器,它使用简单而且能够轻松地在不同的游戏引擎中 ...
- X-UniTMX:导入大型Tiled地图文件(*.tmx)到Unity3d中比较好的插件
因工作原因,需要导入格子数为1200x1200的Tiled地图文件(*.tmx)到Unity3d中显示出来.尝试过一些其它插件,后面发现X-UniTMX是比较好用的. X-UniTMXhttp://f ...
- 如何在Cocos2D游戏中实现A*寻路算法(一)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...
- C# 程序中嵌入百度地图
本例是对WinForm中使用百度地图的简要介绍.百度地图目前支持Android开发,IOS开发,Web开发,服务接口,具体可以参照'百度地图开放平台'. [动态加载百度地图]涉及到的知识点: WebB ...
- 在ionic/cordova中使用百度地图插件
在ionic项目中,如果想实现定位功能,可以使用ng-cordova提供的cordova-plugin-geolocation. 但由于高墙的缘故,国内andorid环境下,此插件不起作用(ios环境 ...
- Android 百度地图开发(一)--- 申请API Key和在项目中显示百度地图
标签: Android百度地图API Key 分类: Android 百度地图开发(2) 最近自己想研究下地图,本来想研究google Map,但是申请API key比较坑爹,于是从百度地 ...
- Android应用中使用百度地图API并加入标注(一)
网上一些资料这样的的内容已经过时了,这里是最新的内容,假设哪里不正确,请吐槽... 1)下载百度地图移动版API(Android)开发包 要在Android应用中使用百度地图API,就须要 ...
- 如何在cocos2d项目中enable ARC
如何在cocos2d项目中enable ARC 基本思想就是不支持ARC的代码用和支持ARC的分开,通过xcode中设置编译选项,让支持和不支持ARC的代码共存. cocos2d是ios app开发中 ...
- Ionic2系列——在Ionic2中使用高德地图
之前讲过了如何在Ionic2中使用第三方库,因为第三方库必须针对TypeScript提供相应的声明文件——即d.ts文件,才能被TypeScript正确识别并编译.好在大多数的第三方库已经有了定义文件 ...
随机推荐
- NopCommerce 3.3中文语言包发布下载及使用
NopCommerce 3.3是一套国外优秀的开源电子商务项目,其拥有完整的电子商务功能且具有灵活的配置功能,基于微软最新技术ASP.NET MVC 5.1.1,EntityFramework.6.1 ...
- 使用DBUtils小框架
DBUtils对sqlserver好像支持不怎么好,经常出现问题 比如 三月 14, 2015 10:19:32 上午 com.mchange.v2.log.MLog 信息: MLog clients ...
- node.js及相关组件安装
第一步:下载安装文件(下载地址:官网http://www.nodejs.org/download/ )第二步:安装nodejs(双击直接安装) 安装完成后使用命令行查看版本信息,出现版本号说明安装成功 ...
- abiword Namespace List
abiword Namespace List Here is a list of all namespaces with brief descriptions: abicollab 这个命名空间以及 ...
- T-SQL 脚本
1.USE语句 USE语句用于设置当前数据库,如果没有USE语句,那么就由执行脚本的任何用户来确定执行脚本时当前数据库是正确的.如果只是一个通用脚本,那么省去USE语句实际上可能更有益.通常,如果在脚 ...
- ArcGis API FOR Silverlight 做了个导航工具~
原文 http://www.cnblogs.com/thinkaspx/archive/2012/08/08/2628214.html 转载请注明文章出处:http://www.cnblogs.com ...
- expect set timeout -1 永不超时
. ~/.bash_profile passwd='xxx' expect <<! set timeout -1 spawn rsync -avH /webapps/Seeyon/A8/b ...
- Linux系统编程(13)——Shell的基本语法
按照惯例,Shell变量由全大写字母加下划线组成,有两种类型的Shell变量:环境变量和本地变量. 环境变量: 环境变量可以从父进程传给子进程,因此Shell进程的环境变量可以从当前Shell进程传给 ...
- C#/vbscript/JS如何加密保护HTML/javascript源代码
原文地址:http://www.coding123.net/article/20121008/encrypt-javascript-by-charp-vbscript.aspx 本文通过将源代码进行u ...
- js查找和过滤
通常情况下选择器可以直接定位到我们想要的元素,但是,当我们拿到一个jQuery对象后,还可以以这个对象为基准,进行查找和过滤. 最常见的查找是在某个节点的所有子节点中查找,使用find()方法,它本身 ...