TMXMap解析
来源:互联网 发布:windows如何设置锁屏 编辑:程序博客网 时间:2024/06/07 02:51
TMXMap.h
#ifndef __CCTMX_TILE_MAP_H__#define __CCTMX_TILE_MAP_H__#include "CCNode.h"#include "CCTMXObjectGroup.h"#include "CCValue.h"NS_CC_BEGIN// TMXMap 需要包含的类class TMXObjectGroup;class TMXLayer;class TMXLayerInfo;class TMXTilesetInfo;class TMXMapInfo;/** 地图方向 */enum{ /** 直角地图 */ TMXOrientationOrtho, /** 六边形地图 */ TMXOrientationHex, /** 45度斜角地图 */ TMXOrientationIso,};/**特点:-每个图块都会被当做sprite处理-精灵只有在需要的时候才被创建,他们只有当你使用"layer->tileAt(position)"创建-每个图块可以使用旋转,放大,缩小等等操作-图块在程序运行的时候可以移除-TMX地图的锚点时(0 ,0)-地图图块的z轴值可以动态变更-图块的锚点时(0 ,0)-TMX图层被当做Layer添加-TNX图层有自己的名称-图块会使用TextureCache添加-每个图块都有自己特有的标签-每个图块都有z轴值,左上方z为0,右下方z轴值最大-每个对象组都会被当做Array处理-对象类使用字典包含所有的属性-各个属性会被分配到地图,层,对象组和对象中限制:-每个地图层最多支持一套瓦片素材组-被嵌套的瓦片地图不被支持(如 使用瓦片素材组与其他图片)-只支持XMl数据格式技术性描述TMX地图使用TMXLayer加载图层,如果图层设置为不可见,程序不会加载图层可以通过- map->getChildByTag(tag_number); // 0=1st layer, 1=2nd layer, 2=3rd layer, etc...- map->getLayer(name_of_the_layer);获取图层每个对象组都会使用TMXObjectGroup加载对象,可以通过getObjectGroup()函数获取对象组每个对象都是TMXObject。每个属性都会存储在字典数组中map->getProperty(name_of_the_property);layer->getProperty(name_of_the_property);objectGroup->getProperty(name_of_the_property);object->getProperty(name_of_the_property);*/class CC_DLL TMXTiledMap : public Node{public: /** 静态函数 根据路径创建TMXMap*/ static TMXTiledMap* create(const std::string& tmxFile); /** 使用XML数据导入地图 */ static TMXTiledMap* createWithXML(const std::string& tmxString, const std::string& resourcePath); /** 获取图层 */ TMXLayer* getLayer(const std::string& layerName) const; /** * @js NA * @lua NA */ CC_DEPRECATED_ATTRIBUTE TMXLayer* layerNamed(const std::string& layerName) const { return getLayer(layerName); }; /** 返回对象组 */ TMXObjectGroup* getObjectGroup(const std::string& groupName) const; /** * @js NA * @lua NA */ CC_DEPRECATED_ATTRIBUTE TMXObjectGroup* objectGroupNamed(const std::string& groupName) const { return getObjectGroup(groupName); }; /** 通过属性名获取属性 */ Value getProperty(const std::string& propertyName) const; /** * @js NA * @lua NA */ CC_DEPRECATED_ATTRIBUTE Value propertyNamed(const char *propertyName) const { return getProperty(propertyName); }; /**返回属性字典,每个图块都有一个id */ Value getPropertiesForGID(int GID) const; CC_DEPRECATED_ATTRIBUTE Value propertiesForGID(int GID) const { return getPropertiesForGID(GID); }; /** 根据GID,获得属性字典 */ bool getPropertiesForGID(int GID, Value** value); /** 地图的大小获取与设置 */ inline const Size& getMapSize() const { return _mapSize; }; inline void setMapSize(const Size& mapSize) { _mapSize = mapSize; }; /** 返回图块大小,以像素点为单位 */ inline const Size& getTileSize() const { return _tileSize; }; inline void setTileSize(const Size& tileSize) { _tileSize = tileSize; }; /** 地图的朝向 */ inline int getMapOrientation() const { return _mapOrientation; }; inline void setMapOrientation(int mapOrientation) { _mapOrientation = mapOrientation; }; /** 获取对象数组 */ inline const Vector<TMXObjectGroup*>& getObjectGroups() const { return _objectGroups; }; inline Vector<TMXObjectGroup*>& getObjectGroups() { return _objectGroups; }; inline void setObjectGroups(const Vector<TMXObjectGroup*>& groups) { _objectGroups = groups; }; /** 获取与设置属性 */ inline ValueMap& getProperties() { return _properties; }; inline void setProperties(const ValueMap& properties) { _properties = properties; }; virtual std::string getDescription() const override; CC_CONSTRUCTOR_ACCESS: /** * @js ctor */ TMXTiledMap(); /** * @js NA * @lua NA */ virtual ~TMXTiledMap(); /** 根据路径获取地图数据 */ bool initWithTMXFile(const std::string& tmxFile); /** XML字符串与资源路径创建Map */ bool initWithXML(const std::string& tmxString, const std::string& resourcePath);protected: TMXLayer * parseLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo); TMXTilesetInfo * tilesetForLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo); void buildWithMapInfo(TMXMapInfo* mapInfo); /** 地图大小 */ Size _mapSize; /** 图块大小 */ Size _tileSize; /** 地图朝向 */ int _mapOrientation; /** 对象数组 */ Vector<TMXObjectGroup*> _objectGroups; /** 属性 */ ValueMap _properties; //! 图块属性 ValueMapIntKey _tileProperties;private: CC_DISALLOW_COPY_AND_ASSIGN(TMXTiledMap);};// end of tilemap_parallax_nodes group/// @}NS_CC_END#endif //__CCTMX_TILE_MAP_H__
TMXMap.cpp
#include "CCTMXTiledMap.h"#include "CCTMXXMLParser.h"#include "CCTMXLayer.h"#include "CCSprite.h"#include "deprecated/CCString.h" // For StringUtils::format#include <algorithm>NS_CC_BEGIN// 静态函数TMXTiledMap * TMXTiledMap::create(const std::string& tmxFile){ TMXTiledMap *ret = new TMXTiledMap(); if (ret->initWithTMXFile(tmxFile)) { ret->autorelease(); return ret; } CC_SAFE_DELETE(ret); return nullptr;}// 静态函数TMXTiledMap* TMXTiledMap::createWithXML(const std::string& tmxString, const std::string& resourcePath){ TMXTiledMap *ret = new TMXTiledMap(); if (ret->initWithXML(tmxString, resourcePath)) { ret->autorelease(); return ret; } CC_SAFE_DELETE(ret); return nullptr;}// 根据路径生成TMXMapInfo 由TMXMapInfo产生地图bool TMXTiledMap::initWithTMXFile(const std::string& tmxFile){ CCASSERT(tmxFile.size()>0, "TMXTiledMap: tmx file should not be empty"); setContentSize(Size::ZERO); TMXMapInfo *mapInfo = TMXMapInfo::create(tmxFile); if (! mapInfo) { return false; } CCASSERT( !mapInfo->getTilesets().empty(), "TMXTiledMap: Map not found. Please check the filename."); buildWithMapInfo(mapInfo); return true;}// 同上bool TMXTiledMap::initWithXML(const std::string& tmxString, const std::string& resourcePath){ setContentSize(Size::ZERO); TMXMapInfo *mapInfo = TMXMapInfo::createWithXML(tmxString, resourcePath); CCASSERT( !mapInfo->getTilesets().empty(), "TMXTiledMap: Map not found. Please check the filename."); buildWithMapInfo(mapInfo); return true;}TMXTiledMap::TMXTiledMap() :_mapSize(Size::ZERO) ,_tileSize(Size::ZERO) {}TMXTiledMap::~TMXTiledMap(){}// 解析层TMXLayer * TMXTiledMap::parseLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo){ TMXTilesetInfo *tileset = tilesetForLayer(layerInfo, mapInfo); TMXLayer *layer = TMXLayer::create(tileset, layerInfo, mapInfo); //用于使Info释放the tiles map. layerInfo->_ownTiles = false; layer->setupTiles(); return layer;}TMXTilesetInfo * TMXTiledMap::tilesetForLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo){ Size size = layerInfo->_layerSize; auto& tilesets = mapInfo->getTilesets(); if (tilesets.size()>0) { TMXTilesetInfo* tileset = nullptr; for (auto iter = tilesets.crbegin(); iter != tilesets.crend(); ++iter) { tileset = *iter; if (tileset) { for( int y=0; y < size.height; y++ ) { for( int x=0; x < size.width; x++ ) { int pos = static_cast<int>(x + size.width * y); int gid = layerInfo->_tiles[ pos ]; // 关于数据存储的形式 // XXX: gid == 0 --> empty tile if( gid != 0 ) { // Optimization: quick return // 如果层是无效的(如:包含了多于一套素材组)后面会抛出错误 if( (gid & kTMXFlippedMask) >= tileset->_firstGid ) return tileset; } } } } } } // 如果图集为空 打印空层名称 CCLOG("cocos2d: Warning: TMX Layer '%s' has no tiles", layerInfo->_name.c_str()); return nullptr;}// 根据MapInfo数据结构创建TMXMap地图void TMXTiledMap::buildWithMapInfo(TMXMapInfo* mapInfo){ _mapSize = mapInfo->getMapSize(); _tileSize = mapInfo->getTileSize(); _mapOrientation = mapInfo->getOrientation(); _objectGroups = mapInfo->getObjectGroups(); _properties = mapInfo->getProperties(); _tileProperties = mapInfo->getTileProperties(); int idx=0; auto& layers = mapInfo->getLayers(); for(const auto &layerInfo : layers) { if (layerInfo->_visible) { // TMXLayer 使用addchild添加进children数组 // paraseLaye函数中tilesetForLayer解析LayerInfo生成TMXLayer,注意zorder TMXLayer *child = parseLayer(layerInfo, mapInfo); addChild(child, idx, idx); // update content size with the max size const Size& childSize = child->getContentSize(); Size currentSize = this->getContentSize(); currentSize.width = std::max( currentSize.width, childSize.width ); currentSize.height = std::max( currentSize.height, childSize.height ); this->setContentSize(currentSize); idx++; } }}// publicTMXLayer * TMXTiledMap::getLayer(const std::string& layerName) const{ CCASSERT(layerName.size() > 0, "Invalid layer name!"); for (auto& child : _children) { TMXLayer* layer = dynamic_cast<TMXLayer*>(child); if(layer) { if(layerName.compare( layer->getLayerName()) == 0) { return layer; } } } // layer not found return nullptr;}TMXObjectGroup * TMXTiledMap::getObjectGroup(const std::string& groupName) const{ CCASSERT(groupName.size() > 0, "Invalid group name!"); if (_objectGroups.size()>0) { TMXObjectGroup* objectGroup = nullptr; for (auto iter = _objectGroups.cbegin(); iter != _objectGroups.cend(); ++iter) { objectGroup = *iter; if (objectGroup && objectGroup->getGroupName() == groupName) { return objectGroup; } } } // objectGroup not found return nullptr;}Value TMXTiledMap::getProperty(const std::string& propertyName) const{ if (_properties.find(propertyName) != _properties.end()) return _properties.at(propertyName); return Value();}Value TMXTiledMap::getPropertiesForGID(int GID) const{ if (_tileProperties.find(GID) != _tileProperties.end()) return _tileProperties.at(GID); return Value();}bool TMXTiledMap::getPropertiesForGID(int GID, Value** value){ if (_tileProperties.find(GID) != _tileProperties.end()) { *value = &_tileProperties.at(GID); return true; } else { return false; }}std::string TMXTiledMap::getDescription() const{ return StringUtils::format("<TMXTiledMap | Tag = %d, Layers = %d", _tag, static_cast<int>(_children.size()));}NS_CC_END
通过上面代码解析,可以看到TMXMap依据路径创建Info数据结构,然后TMXLayer通过Info数据结构生成Layer。很多人会忽略掉一个层只能使用一个地图集的限制,具体意思是指比如说一个层,引用了一个图块集后,我再引用不同的一个地图集,两个地图集的图块放置在同一层上,程序会报错,tiled规范不允许这样做。
TMXLayer.h
#ifndef __CCTMX_LAYER_H__#define __CCTMX_LAYER_H__#include "CCTMXObjectGroup.h"#include "CCAtlasNode.h"#include "CCSpriteBatchNode.h"#include "CCTMXXMLParser.h"#include "ccCArray.h"NS_CC_BEGINclass TMXMapInfo;class TMXLayerInfo;class TMXTilesetInfo;struct _ccCArray;/** TMXLayer是SpriteBathNode的子类,并非Layer子类。图块的渲染使用TextureAtlas如果在程序运行时修改了图块,然后,图块会变成Sprite,否则没有Sprite产生这就意味着图块能够像Sprite一样放大缩小旋转等等操作层包含了一个叫做cc_vertexz属性,层会使用这个属性当做Opengl渲染的z轴深度值从另外一个方面来说 如果cc_vertexz是一个automatic(自动)值,图块也就拥有了一个自动变化的z轴值所有属于这个层的图块都会把这个值当做z轴值同时在图块被绘制之前,GL_ALPHA_TEST会开启,在绘制完毕后关闭,用于alpha功能实现glAlphaFunc( GL_GREATER, value )alpha的值可以时0,你也可以变更它,使用地图层的属性cc_alpha_func设置,手法与cc_vertexz一致默认数值为0*/class CC_DLL TMXLayer : public SpriteBatchNode{public: /** 静态方法 依据tiled ,Layer ,map数据结构生成Layer */ static TMXLayer * create(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo); TMXLayer(); virtual ~TMXLayer(); /** 使用tiled ,layer ,map数据初始化 这类手法在cocos太常见了 */ bool initWithTilesetInfo(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo); /** 释放地图 一般不用管其中的实现 因为引擎已经封装好了 不懂的可以去看cocos2d-x内存机制 */ void releaseMap(); /** 以Sprite的形式返回参数数据位置上的图块 返回的同时也会添加到TMXLayer中,不要反复添加 可以对返回Sprite进行Sprite操作 也可以删除 - layer->removeChild(sprite, cleanup); - or layer->removeTileAt(Point(x,y)); */ Sprite* getTileAt(const Point& tileCoordinate); CC_DEPRECATED_ATTRIBUTE Sprite* tileAt(const Point& tileCoordinate) { return getTileAt(tileCoordinate); }; /** 根据地址返回图块gid,前提条件时map没有被显式释放 */ uint32_t getTileGIDAt(const Point& tileCoordinate, TMXTileFlags* flags = nullptr); CC_DEPRECATED_ATTRIBUTE uint32_t tileGIDAt(const Point& tileCoordinate, TMXTileFlags* flags = nullptr){ return getTileGIDAt(tileCoordinate, flags); }; /** 设置gid */ void setTileGID(uint32_t gid, const Point& tileCoordinate); /** 同上 */ void setTileGID(uint32_t gid, const Point& tileCoordinate, TMXTileFlags flags); /** 移除一个地图块 */ void removeTileAt(const Point& tileCoordinate); /** 以像素点为单位返回指定地图点上的位置 */ Point getPositionAt(const Point& tileCoordinate); CC_DEPRECATED_ATTRIBUTE Point positionAt(const Point& tileCoordinate) { return getPositionAt(tileCoordinate); }; /** 返回属性的值 */ Value getProperty(const std::string& propertyName) const; CC_DEPRECATED_ATTRIBUTE Value propertyNamed(const std::string& propertyName) const { return getProperty(propertyName); }; /** 标题 */ void setupTiles(); inline const std::string& getLayerName(){ return _layerName; } inline void setLayerName(const std::string& layerName){ _layerName = layerName; } /** size of the layer in tiles */ inline const Size& getLayerSize() const { return _layerSize; }; inline void setLayerSize(const Size& size) { _layerSize = size; }; /** 获取和设置图块大小 */ inline const Size& getMapTileSize() const { return _mapTileSize; }; inline void setMapTileSize(const Size& size) { _mapTileSize = size; }; uint32_t* getTiles() const { return _tiles; }; void setTiles(uint32_t* tiles) { _tiles = tiles; }; /** 返回层的数据 */ inline TMXTilesetInfo* getTileSet() const { return _tileSet; }; inline void setTileSet(TMXTilesetInfo* info) { CC_SAFE_RETAIN(info); CC_SAFE_RELEASE(_tileSet); _tileSet = info; }; /** 层的旋转角度 */ inline int getLayerOrientation() const { return _layerOrientation; }; inline void setLayerOrientation(int orientation) { _layerOrientation = orientation; }; /** 返回属性集 */ inline const ValueMap& getProperties() const { return _properties; }; inline ValueMap& getProperties() { return _properties; }; inline void setProperties(const ValueMap& properties) { _properties = properties; }; // // Override // /**TMXLayer不支持添加Sprite,替代使用setTiledGID() */ using SpriteBatchNode::addChild; virtual void addChild(Node * child, int zOrder, int tag) override; // super method void removeChild(Node* child, bool cleanup) override; virtual std::string getDescription() const override;private:// 私有方法主要是对内的操作 Point getPositionForIsoAt(const Point& pos); Point getPositionForOrthoAt(const Point& pos); Point getPositionForHexAt(const Point& pos); Point calculateLayerOffset(const Point& offset); /* 数据结构操作方法 */ Sprite* appendTileForGID(uint32_t gid, const Point& pos); Sprite* insertTileForGID(uint32_t gid, const Point& pos); Sprite* updateTileForGID(uint32_t gid, const Point& pos); /* 解析属性 */ void parseInternalProperties(); void setupTileSprite(Sprite* sprite, Point pos, int gid); Sprite* reusedTileWithRect(Rect rect); int getVertexZForPos(const Point& pos); // index ssize_t atlasIndexForExistantZ(int z); ssize_t atlasIndexForNewZ(int z); protected: //! 层的名字 相当于ID 在Map getlayer有明确使用 std::string _layerName; //! TMX Layer supports opacity unsigned char _opacity; //! 整个层的层级 以及是否使用自动变更层级 int _vertexZvalue; bool _useAutomaticVertexZ; //! 供数据结构使用 Sprite *_reusedTile; ccCArray *_atlasIndexArray; // retina 效果 float _contentScaleFactor; /** 层的大小 */ Size _layerSize; /** 地图的大小 */ Size _mapTileSize; /** 指向地图块 */ uint32_t* _tiles; /** 层的数据结构 */ TMXTilesetInfo* _tileSet; /** 层的朝向 与地图的朝向原理一致*/ int _layerOrientation; /** 属性 */ ValueMap _properties;};NS_CC_END#endif //__CCTMX_LAYER_H__从头文件可以看到Layer对外的接口,Layer继承自SpriteBatchNode,大家都知道SpriteBatchNode的作用吧,不懂的自己去搜,SpriteBatchNode里面主要有Texture2D对象和一个存储要渲染的数组,实现大批次渲染。
下面是cpp的解析
TMXLayer * TMXLayer::create(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo){ TMXLayer *ret = new TMXLayer(); if (ret->initWithTilesetInfo(tilesetInfo, layerInfo, mapInfo)) { ret->autorelease(); return ret; } return nullptr;}
转入bool TMXLayer::initWithTilesetInfo(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo)
bool TMXLayer::initWithTilesetInfo(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo){ // XXX: is 35% a good estimate ? Size size = layerInfo->_layerSize; float totalNumberOfTiles = size.width * size.height; float capacity = totalNumberOfTiles * 0.35f + 1; // 35 percent is occupied ?// texture加载地图集图块,一个层只有一个地图集 Texture2D *texture = nullptr; if( tilesetInfo ) { texture = Director::getInstance()->getTextureCache()->addImage(tilesetInfo->_sourceImage.c_str()); }// 加载相关的地图信息 if (SpriteBatchNode::initWithTexture(texture, static_cast<ssize_t>(capacity))) { // 地图层数据 _layerName = layerInfo->_name; _layerSize = size; _tiles = layerInfo->_tiles; _opacity = layerInfo->_opacity; setProperties(layerInfo->getProperties()); _contentScaleFactor = Director::getInstance()->getContentScaleFactor(); // 地图图块数据 _tileSet = tilesetInfo; CC_SAFE_RETAIN(_tileSet); // 地图数据 _mapTileSize = mapInfo->getTileSize(); _layerOrientation = mapInfo->getOrientation(); // 地图层偏移 Point offset = this->calculateLayerOffset(layerInfo->_offset); this->setPosition(CC_POINT_PIXELS_TO_POINTS(offset)); _atlasIndexArray = ccCArrayNew(totalNumberOfTiles); this->setContentSize(CC_SIZE_PIXELS_TO_POINTS(Size(_layerSize.width * _mapTileSize.width, _layerSize.height * _mapTileSize.height))); _useAutomaticVertexZ = false; _vertexZvalue = 0; return true; } return false;}
加载完成地图层信息后,进入下一个函数 layer->setupTiles();// 放置地图集中的图块
关键部分
if (gid != 0) { this->appendTileForGID(gid, Point(x, y)); }
跳入appendTileForGID函数中setupTileSprite函数是对精灵进行一些位置等等设置。
接下来比较关键的代码是这段
insertQuadFromSprite(tile, indexForZ); //tled是精灵
从这段代码转入SpriteBatchNode,成功进行添加。
PS:当地图层设置为不可见时,地图的设置信息还是会加载,但是图层不会生成TMXLayer
代码void TMXTiledMap::buildWithMapInfo(TMXMapInfo* mapInfo)中
auto& layers = mapInfo->getLayers(); for(const auto &layerInfo : layers) { if (layerInfo->_visible) {
0 0
- TMXMap解析
- TMXMap学习总结
- Cocos2d-x 3.x游戏开发之旅---(TMXMap的操作)
- 解析
- 解析
- 解析
- 解析
- 解析
- 解析
- 解析
- 解析
- 解析
- 解析[ ]
- 解析
- ffmpeg解析-----解析文件格式
- Xen解析 netfilter解析
- JSON解析,XML解析
- 硬解析 软解析
- Intent传递对象(两种序列化方式Serializable/Parcelable)
- C#网络编程中
- hadoop权威指南 chapter2 MapReduce
- segue实现两个页面传值
- 关于android的权限问题
- TMXMap解析
- APUE——信号
- fstat函数
- struts1标签之<logic:iterate>
- Qtopia4.2.4移植时出现:The tslib functionality test failed!
- poj 1860&poj2240 似负环
- HDOJ 2736 Surprising Strings——c++STL(map)
- MySql下视图的创建
- POJ2109