cocos2dx源代码分析之TMXTiled 瓦片地图

来源:互联网 发布:电脑条码识别软件 编辑:程序博客网 时间:2024/04/29 18:32

     关于cocos2dx 中的瓦片地图的分析


在游戏制作当中瓦片地图的使用可以大大减少工程的大小很多特别是很多不断重复图片的使用,一个比较大的地图比如

最近流行的部落冲突游戏很明显的是使用了瓦片地图,我觉得瓦片地图的使用适用用于以下的几种游戏

1,.特别适用于很大的地图如果背景但是背景的重复性高的话,使用瓦片地图是一个很好的选择

2,.针对于很多地图不断变化的游戏,例如游戏中需要种树或者删除一小块的元

3.类似于超级马里奥那种的横版的游戏,都是又一个个小的方块组成

 瓦片地图的实现需要使用TileMap这个软件可以百度一下,这个软件是专门用来做瓦片地图的

        没有的可以点击下载

 关于TileMap地图支持3种不同的视图:正交视图        六边形的视图       等轴视图


  在TileMap中的你可以对你所编辑的地图场景进行分层类似于游戏中的Layer一样的,每一层和每一层之间没有

 直接的联系每一个层中是由很多的瓦片组成每一个瓦片都会有一个唯一的编号所以这样的话你会精确的得到地图

中的一个很小的点但是在他中的坐标和coco2d中的坐标不一样的,他的坐标原点在左上角左上角的是(0,0)点了,

 可以对地图中的每一个瓦片进行动态的添加和删除,所以这就是瓦片地图的强大之处。

在瓦片地图中还存在一种对象层可以创建一个不规则的图形一般用于处理一些碰撞什么的

  具体的代码方面可以查看cocos2d 的源代码CCTMXTiledMap.cpp文件

  关于cocos2dx创建方法在可以看到源代码中

TMXTiledMap * TMXTiledMap::create(const std::string& tmxFile){    TMXTiledMap *ret = new (std::nothrow) 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 (std::nothrow) TMXTiledMap();    if (ret->initWithXML(tmxString, resourcePath))    {        ret->autorelease();        return ret;    }    CC_SAFE_DELETE(ret);    return nullptr;}
创建方法有两种可以看到其区别一种是可以传入地图文件的文件路径一种是不传入

接下来是得到成功创建的map的每一层代码

</pre><p></p><p></p><pre name="code" class="cpp">// 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;}

可以看到通过调用getLayer传入层的文件名便可以得到返回的每一层 


 CC_DEPRECATED_ATTRIBUTE TMXLayer* layerNamed(const std::string& layerName) const { return getLayer(layerName); };

或者可以通过直接 layerNamed()得到也只是同理了

 还有一些比如说如何得到总共有多少个瓦片每一个瓦片的大小是多少,根据数量以及大小就可以得到具体你要得到的瓦片的位置

 

    inline const Size& getMapSize() const { return _mapSize; };    inline void setMapSize(const Size& mapSize) { _mapSize = mapSize; };    /** the tiles's size property measured in pixels */    inline const Size& getTileSize() const { return _tileSize; };    inline void setTileSize(const Size& tileSize) { _tileSize = tileSize; };

mapSize 指的是总的地图的大小但是这里的大小指的不是像素的大小这里指的是坐标多少,也就是指的是总共有多少的瓦片

tileSize   指的是每一个瓦片的大小

关于对象层

 

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;}

可以得到对象层的引用然后在对象组里得到你所需要的对象的位置了
        auto heroObject = myTiledMap->getObjectGroup("heroborn");auto spanwnPoint = heroObject->getObject("createHero"); heroBornX = spanwnPoint["x"].asInt(); heroBornY = spanwnPoint["y"].asInt();

那么得到了层之后紧接着就是得到层中的每一个瓦片的点

Sprite * TMXLayer::getTileAt(const Vec2& pos){    CCASSERT(pos.x < _layerSize.width && pos.y < _layerSize.height && pos.x >=0 && pos.y >=0, "TMXLayer: invalid position");    CCASSERT(_tiles && _atlasIndexArray, "TMXLayer: the tiles map has been released");    Sprite *tile = nullptr;    int gid = this->getTileGIDAt(pos);    // if GID == 0, then no tile is present    if (gid)     {        int z = (int)(pos.x + pos.y * _layerSize.width);        tile = static_cast<Sprite*>(this->getChildByTag(z));        // tile not created yet. create it        if (! tile)         {            Rect rect = _tileSet->getRectForGID(gid);            rect = CC_RECT_PIXELS_TO_POINTS(rect);            tile = Sprite::createWithTexture(this->getTexture(), rect);            tile->setBatchNode(this);            tile->setPosition(getPositionAt(pos));            tile->setPositionZ((float)getVertexZForPos(pos));            tile->setAnchorPoint(Vec2::ZERO);            tile->setOpacity(_opacity);            ssize_t indexForZ = atlasIndexForExistantZ(z);            this->addSpriteWithoutQuad(tile, static_cast<int>(indexForZ), z);        }    }        return tile;}
可以通过具体的坐标得到一个以这个坐标为点的精灵

那么接下来可以对每一个瓦片进行增删的操作

 这段的意思就是对每一层进行增加

void TMXLayer::setTileGID(uint32_t gid, const Vec2& pos, TMXTileFlags flags){    CCASSERT(pos.x < _layerSize.width && pos.y < _layerSize.height && pos.x >=0 && pos.y >=0, "TMXLayer: invalid position");    CCASSERT(_tiles && _atlasIndexArray, "TMXLayer: the tiles map has been released");    CCASSERT(gid == 0 || (int)gid >= _tileSet->_firstGid, "TMXLayer: invalid gid" );    TMXTileFlags currentFlags;    uint32_t currentGID = getTileGIDAt(pos, ¤tFlags);    if (currentGID != gid || currentFlags != flags)     {        uint32_t gidAndFlags = gid | flags;        // setting gid=0 is equal to remove the tile        if (gid == 0)        {            removeTileAt(pos);        }        // empty tile. create a new one        else if (currentGID == 0)        {            insertTileForGID(gidAndFlags, pos);        }        // modifying an existing tile with a non-empty tile        else         {            int z = pos.x + pos.y * _layerSize.width;            Sprite *sprite = static_cast<Sprite*>(getChildByTag(z));            if (sprite)            {                Rect rect = _tileSet->getRectForGID(gid);                rect = CC_RECT_PIXELS_TO_POINTS(rect);                sprite->setTextureRect(rect, false, rect.size);                if (flags)                 {                    setupTileSprite(sprite, sprite->getPosition(), gidAndFlags);                }                _tiles[z] = gidAndFlags;            }             else             {                updateTileForGID(gidAndFlags, pos);            }        }    }}
</pre><p></p><p>那么删除操作如下</p><p></p><pre name="code" class="cpp">void TMXLayer::removeTileAt(const Vec2& pos){    CCASSERT(pos.x < _layerSize.width && pos.y < _layerSize.height && pos.x >=0 && pos.y >=0, "TMXLayer: invalid position");    CCASSERT(_tiles && _atlasIndexArray, "TMXLayer: the tiles map has been released");    int gid = getTileGIDAt(pos);    if (gid)     {        int z = pos.x + pos.y * _layerSize.width;        ssize_t atlasIndex = atlasIndexForExistantZ(z);        // remove tile from GID map        _tiles[z] = 0;        // remove tile from atlas position array        ccCArrayRemoveValueAtIndex(_atlasIndexArray, atlasIndex);        // remove it from sprites and/or texture atlas        Sprite *sprite = (Sprite*)getChildByTag(z);        if (sprite)        {            SpriteBatchNode::removeChild(sprite, true);        }        else         {            _textureAtlas->removeQuadAtIndex(atlasIndex);            // update possible children            for(const auto &obj : _children) {                Sprite* child = static_cast<Sprite*>(obj);                ssize_t ai = child->getAtlasIndex();                if ( ai >= atlasIndex )                {                    child->setAtlasIndex(ai-1);                }            }        }    }}



在说一个比较常用的互相转换坐标的函数


CCPoint GameMap::tileCoordForPosition(CCPoint position){int x = position.x / this->getTileSize().width;int y = (((this->getMapSize().height) * this->getTileSize().height) - position.y) / this->getTileSize().height;return ccp(x, y);}CCPoint GameMap::positionForTileCoord(CCPoint tileCoord){CCPoint pos = ccp((tileCoord.x * this->getTileSize().width),((this->getMapSize().height - tileCoord.y) * this->getTileSize().height));return pos;}


关于应用方面可以参考一下这个文章  http://cn.cocos2d-x.org/tutorial/lists?id=83


  

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 身份证地址错了怎么办 学生迁户口学籍怎么办 买新车临时牌怎么办 户口迁移换驾照怎么办 户口迁了身份证怎么办 户口迁移了医保怎么办 房屋卖了户口怎么办 驾照过期注销了怎么办 负全责不赔偿怎么办 青岛驾驶证过期了怎么办 驾驶证过了年检怎么办 驾驶证审证逾期怎么办 d驾驶证3年没捡怎么办 c1驾驶证3年没审怎么办 驾驶证换证外地怎么办 考驾驶证快到期怎么办 驾照到期人在国外怎么办 驾驶证3年没审怎么办c3 驾驶证几年没审怎么办 驾照体检过期了怎么办 b2驾照超过年检怎么办 驾驶证过审一年怎么办 驾照一年未年审怎么办 b驾照年审过期怎么办 摩托车驾驶证过期一年怎么办 驾驶证过期一年半怎么办 驾照过期了几天怎么办 驾照过期超过一年怎么办 考试驾照过期了怎么办 驾校考试过期了怎么办 驾驶证明过期了怎么办 驾驶证年过期了怎么办 驾照过期六个月怎么办 移动预约号码取消怎么办 身份证换地址驾驶证怎么办 刚来成都怎么办居住证 我在外地怎么办身份证 身份证丢在外地怎么办 换领新身份证时旧证丢了怎么办 二代身份证重号怎么办 北京行驶证到期怎么办