您的位置:首页 > 移动开发 > Cocos引擎

cocos2d-x 中 TileMap(块地图 45度视角)的一些问题

2013-07-06 10:37 507 查看
本文采用的cocos2d-x版本是2.1.14

首先,推荐工具tiled,下载不到的朋友可以加我QQ索要安装包。

cocos中对块地图提供了几种不同的类,这里我推荐使用的是CCTMXTiledMap,理由如下:

1,支持平视角 和 45度视角

2,支持多层地图

3,支持地图局部透过(某层某块可以为空)

4,地图编辑工具(tiled)较为方便

下面介绍关于CCTMXTiledMap的用法和技巧:

Features:

- Each tile will be treated as an CCSprite

- The sprites are created on demand. They will be created only when you call "layer->tileAt(position)"

- Each tile can be rotated / moved / scaled / tinted / "opaqued", since each tile is a CCSprite

- Tiles can be added/removed in runtime

- The z-order of the tiles can be modified in runtime

- Each tile has an anchorPoint of (0,0)

- The anchorPoint of the TMXTileMap is (0,0)

- The TMX layers will be added as a child

- The TMX layers will be aliased by default

- The tileset image will be loaded using the CCTextureCache

- Each tile will have a unique tag

- Each tile will have a unique z value. top-left: z=1, bottom-right: z=max z

- Each object group will be treated as an CCMutableArray

- Object class which will contain all the properties in a dictionary

- Properties can be assigned to the Map, Layer, Object Group, and Object

这是头文件中给出的说明,不懂英文的同学自己谷歌翻译。

首先,从头文件的声明

/** the map's size property measured in tiles */

CC_SYNTHESIZE_PASS_BY_REF(CCSize, m_tMapSize, MapSize);

/** the tiles's size property measured in pixels */

CC_SYNTHESIZE_PASS_BY_REF(CCSize, m_tTileSize, TileSize);

两行我们可以知道,可以通过MapSize()来获得地图块的行数和列数

可以通过TileSize()来获得每一块的像素宽和像素高

当然,因为CCTMXTiledMap本身继承自CCNode,所以CCNode自身的Size属性和Postion属性CCTMXTiledMap也是有的。

其次,从说明中,我们可以得知CCTMXTiledMap是由多个CCTMXLayer构成的,我们可以通过CCTMXLayer* layerNamed(const char *layerName)来得到Layer的指针。

关于LayerName,一般是在编辑tmx文件(地图文件)时编辑的,如果tmx文件不是你自己编辑的,可以通过写字板打开tmx文件,在

"<layer name="LayerOne" width="50" height="50">"一行看到层的名字。

在CCTMXLayer中,我们可以通过tileAt(position)来获得每个块的指针,并且将这个块作为CCSprite来操作。

注意:postion的起始坐标(0,0)是地图的左上角(45度地图是正上方角)

也可以通过positionAt()来获得某块地图在大地图上的坐标(注意:锚点是(0,0))

在实际使用中,提问最多的问题 是在45度坐标系下 如何将 触摸点 换算成 地图块坐标(如何知道触摸了哪个地图块)

这里我给出一个坐标变换函数,仅供大家参考:

//将屏幕触摸点换算成 Map块坐标(45度视角地图)

bool CIsoMapLayer::GetTilePosFromScreenPos( const CCPoint ptTouchPoint,CCPoint &ptTilePos )

{

do

{

CCTMXTiledMap* pIOSMap = dynamic_cast<CCTMXTiledMap*>(getChildByTag(enTagMap));

CC_BREAK_IF(pIOSMap==NULL);

//数据校验

CC_BREAK_IF(pIOSMap->getMapSize().width==0||pIOSMap->getMapSize().height==0);

//将屏幕坐标 转换成 Map节点 内坐标

CCPoint ptMapPoint = pIOSMap->convertToNodeSpace(ptTouchPoint);

CCSize sizeMap = pIOSMap->getMapSize();

CCSize sizeTile = pIOSMap->getTileSize();

CCSize sizeNode = pIOSMap->getContentSize();

float fTileSin = GetSinFromMap(pIOSMap);//计算Sin角,请用户自行编写

float fTileCos = GetCosFromMap(pIOSMap);//计算Cos角,请用户自行编写

float fTileTan = sizeTile.height/sizeTile.width;

CC_BREAK_IF(fTileSin==0||fTileCos==0);

//地图块在新坐标系下大小

float fTileWidth = sizeTile.width*0.5f/fTileCos;

float fTileHeight = sizeTile.height*0.5f/fTileSin;//值应该与Weight相同,因为理论上还是方块的

//地图总大小(新坐标系下)

float fMapTotalWidth =fTileWidth*sizeMap.width;

float fMapTotalHeight =fTileHeight*sizeMap.height;//地图总体Size不一定是方形的

//坐标系变换公式

float fMapPosX = (ptMapPoint.x-(ptMapPoint.y-sizeNode.height*0.5f)/fTileTan)*0.5f/fTileCos;

int nXPos = (int)(fMapPosX/fTileWidth);

float fMapPosY = (ptMapPoint.y-sizeNode.height*0.5f)*0.5f/fTileSin+ptMapPoint.x*0.5f/fTileCos;

int nYPos =(int)(fMapPosY/fTileHeight);

//检查是否点击在地图上

if(nYPos<0||nXPos<0)return false;

if(nYPos>=sizeMap.height||nXPos>=sizeMap.width)return false;

//得到地图块坐标

ptTilePos = ccp(nXPos,pIOSMap->getMapSize().height-1-nYPos);

return true;

} while (false);

return false;

}

本人常年承接各类cocos2d-x培训 技术外包 架构指导等工作

QQ:2813610155

Tel:18640244143
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: