Cocos2d-x源代码解析(1)——地图模块(3)

接上一章《Cocos2d-x源代码解析(1)——地图模块(2)》

通过前面两章的分析,我们能够知道cocos将tmx的信息结构化到 CCTMXMapInfo。CCTMXTilesetInfo,CCTMXLayerInfo之中。

当中CCTMXMapInfo存储地图的信息包扩下面几块信息:

- Map orientation (hexagonal, isometric or orthogonal)

- Tile size

- Map size

- Layers (an array of TMXLayerInfo objects)

- Tilesets (an array of TMXTilesetInfo objects)

- ObjectGroups (an array of TMXObjectGroupInfo objects)

CCTMXTilesetInfo存储瓦片信息包含:

- Tileset name

- Tileset spacing

- Tileset margin

- size of the tiles

- Image used for the tiles

- Image size

CCTMXLayerInfo存储层的信息包含:

-
Layer name

- Layer size

- Layer opacity at creation time (it can be modified at runtime)

- Whether the layer is visible (if it‘s not visible, then the CocosNode won‘t be created)

接下来,我们分析cocos怎样通过这些信息,生成地图的图像:

首先我们看一个重要的函数buildWithMapInfo

void CCTMXTiledMap::buildWithMapInfo(CCTMXMapInfo* mapInfo)
{
    m_tMapSize = mapInfo->getMapSize();
    m_tTileSize = mapInfo->getTileSize();
    m_nMapOrientation = mapInfo->getOrientation();

    CC_SAFE_RELEASE(m_pObjectGroups);
    m_pObjectGroups = mapInfo->getObjectGroups();
    CC_SAFE_RETAIN(m_pObjectGroups);

    CC_SAFE_RELEASE(m_pProperties);
    m_pProperties = mapInfo->getProperties();
    CC_SAFE_RETAIN(m_pProperties);

    CC_SAFE_RELEASE(m_pTileProperties);
    m_pTileProperties = mapInfo->getTileProperties();
    CC_SAFE_RETAIN(m_pTileProperties);

    int idx=0;

    CCArray* layers = mapInfo->getLayers();
    if (layers && layers->count()>0)
    {
        CCTMXLayerInfo* layerInfo = NULL;
        CCObject* pObj = NULL;
        CCARRAY_FOREACH(layers, pObj)
        {
            layerInfo = (CCTMXLayerInfo*)pObj;
            if (layerInfo && layerInfo->m_bVisible)
            {
                CCTMXLayer *child = parseLayer(layerInfo, mapInfo);
                addChild((CCNode*)child, idx, idx);

                // update content size with the max size
                const CCSize& childSize = child->getContentSize();
                CCSize currentSize = this->getContentSize();
                currentSize.width = MAX( currentSize.width, childSize.width );
                currentSize.height = MAX( currentSize.height, childSize.height );
                this->setContentSize(currentSize);

                idx++;
            }
        }
    }
}

这个函数首相将地图信息赋给map类。接下来对于每一个layer进行处理,重要的函数是parseLayer,这个函数是将layer的信息处理好而且加上sprite,并生成CTMXlayer对象。

因此我们须要分析parseLayer函数和CTMXlayer类。

首先我们看CTMXlayer的声明:

class CC_DLL CCTMXLayer : public CCSpriteBatchNode
{
    /** size of the layer in tiles */
    CC_SYNTHESIZE_PASS_BY_REF(CCSize, m_tLayerSize, LayerSize);
    /** size of the map's tile (could be different from the tile's size) */
    CC_SYNTHESIZE_PASS_BY_REF(CCSize, m_tMapTileSize, MapTileSize);
    /** pointer to the map of tiles */
    CC_SYNTHESIZE(unsigned int*, m_pTiles, Tiles);
    /** Tileset information for the layer */
    CC_PROPERTY(CCTMXTilesetInfo*, m_pTileSet, TileSet);
    /** Layer orientation, which is the same as the map orientation */
    CC_SYNTHESIZE(unsigned int, m_uLayerOrientation, LayerOrientation);
    /** properties from the layer. They can be added using Tiled */
    CC_PROPERTY(CCDictionary*, m_pProperties, Properties);
public:
    /**
     * @js ctor
     * @lua NA
     */
    CCTMXLayer();
    /**
     * @js NA
     * @lua NA
     */
    virtual ~CCTMXLayer();

    /** creates a CCTMXLayer with an tileset info, a layer info and a map info */
    static CCTMXLayer * create(CCTMXTilesetInfo *tilesetInfo, CCTMXLayerInfo *layerInfo, CCTMXMapInfo *mapInfo);

    /** initializes a CCTMXLayer with a tileset info, a layer info and a map info
     * @lua NA
     */
    bool initWithTilesetInfo(CCTMXTilesetInfo *tilesetInfo, CCTMXLayerInfo *layerInfo, CCTMXMapInfo *mapInfo);

    /** dealloc the map that contains the tile position from memory.
    Unless you want to know at runtime the tiles positions, you can safely call this method.
    If you are going to call layer->tileGIDAt() then, don't release the map
    */
    void releaseMap();

    /** returns the tile (CCSprite) at a given a tile coordinate.
    The returned CCSprite will be already added to the CCTMXLayer. Don't add it again.
    The CCSprite can be treated like any other CCSprite: rotated, scaled, translated, opacity, color, etc.
    You can remove either by calling:
    - layer->removeChild(sprite, cleanup);
    - or layer->removeTileAt(ccp(x,y));
    @js getTileGIDAt
    */
    CCSprite* tileAt(const CCPoint& tileCoordinate);

    /** returns the tile gid at a given tile coordinate.
    if it returns 0, it means that the tile is empty.
    This method requires the the tile map has not been previously released (eg. don't call layer->releaseMap())
    @js tileGIDAt
    */
    unsigned int  tileGIDAt(const CCPoint& tileCoordinate);

    /** returns the tile gid at a given tile coordinate. It also returns the tile flags.
     This method requires the the tile map has not been previously released (eg. don't call [layer releaseMap])
     @js tileGIDAt
     @lua NA
     */
    unsigned int tileGIDAt(const CCPoint& tileCoordinate, ccTMXTileFlags* flags);

    /** sets the tile gid (gid = tile global id) at a given tile coordinate.
    The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor -> Tileset Mgr +1.
    If a tile is already placed at that position, then it will be removed.
    */
    void setTileGID(unsigned int gid, const CCPoint& tileCoordinate);

    /** sets the tile gid (gid = tile global id) at a given tile coordinate.
     The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor -> Tileset Mgr +1.
     If a tile is already placed at that position, then it will be removed.

     Use withFlags if the tile flags need to be changed as well
     */

    void setTileGID(unsigned int gid, const CCPoint& tileCoordinate, ccTMXTileFlags flags);

    /** removes a tile at given tile coordinate */
    void removeTileAt(const CCPoint& tileCoordinate);

    /** returns the position in points of a given tile coordinate
     * @js getPositionAt
     */
    CCPoint positionAt(const CCPoint& tileCoordinate);

    /** return the value for the specific property name
     *  @js getProperty
     */
    CCString *propertyNamed(const char *propertyName);

    /** Creates the tiles */
    void setupTiles();

    /** CCTMXLayer doesn't support adding a CCSprite manually.
     *  @warning addchild(z, tag); is not supported on CCTMXLayer. Instead of setTileGID.
     *  @lua NA
     */
    virtual void addChild(CCNode * child, int zOrder, int tag);
    /** super method
     *  @lua NA
     */
    void removeChild(CCNode* child, bool cleanup);

    inline const char* getLayerName(){ return m_sLayerName.c_str(); }
    inline void setLayerName(const char *layerName){ m_sLayerName = layerName; }
private:
    CCPoint positionForIsoAt(const CCPoint& pos);
    CCPoint positionForOrthoAt(const CCPoint& pos);
    CCPoint positionForHexAt(const CCPoint& pos);

    CCPoint calculateLayerOffset(const CCPoint& offset);

    /* optimization methods */
    CCSprite* appendTileForGID(unsigned int gid, const CCPoint& pos);
    CCSprite* insertTileForGID(unsigned int gid, const CCPoint& pos);
    CCSprite* updateTileForGID(unsigned int gid, const CCPoint& pos);

    /* The layer recognizes some special properties, like cc_vertez */
    void parseInternalProperties();
    void setupTileSprite(CCSprite* sprite, CCPoint pos, unsigned int gid);
    CCSprite* reusedTileWithRect(CCRect rect);
    int vertexZForPos(const CCPoint& pos);

    // index
    unsigned int atlasIndexForExistantZ(unsigned int z);
    unsigned int atlasIndexForNewZ(int z);
protected:
    //! name of the layer
    std::string m_sLayerName;
    //! TMX Layer supports opacity
    unsigned char        m_cOpacity;

    unsigned int        m_uMinGID;
    unsigned int        m_uMaxGID;

    //! Only used when vertexZ is used
    int                    m_nVertexZvalue;
    bool                m_bUseAutomaticVertexZ;

    //! used for optimization
    CCSprite            *m_pReusedTile;
    ccCArray            *m_pAtlasIndexArray;

    // used for retina display
    float               m_fContentScaleFactor;
};

尽管有一大堆的属性和函数,可是归根结底他是一个CCSpriteBatchNode对象,因为地图中非常多图片是同样的。CCSpriteBatchNode就是cocos2d-x为了减少渲染批次而建立的一个专门管理精灵的类。

然后是函数parseLayer

CCTMXLayer * CCTMXTiledMap::parseLayer(CCTMXLayerInfo *layerInfo, CCTMXMapInfo *mapInfo)
{
    CCTMXTilesetInfo *tileset = tilesetForLayer(layerInfo, mapInfo);
    CCTMXLayer *layer = CCTMXLayer::create(tileset, layerInfo, mapInfo);

    // tell the layerinfo to release the ownership of the tiles map.
    layerInfo->m_bOwnTiles = false;
    layer->setupTiles();

    return layer;
}

这个函数又分为3步

第一步tilesetForLayer是拿到随意一块属于这个layer的tile。

第二步是依据layerInfo创建一个真正的层信息。

第三步是将tiled增加到这个层中去。

时间: 2024-11-06 18:39:47

Cocos2d-x源代码解析(1)——地图模块(3)的相关文章

thttpd源代码解析 定时器模块

thttpd源代码解析 定时器模块 thttpd是很轻量级的httpserver,可运行文件仅50kB.名称中的第一个t表示tiny, turbo, 或throttling 与lighttpd.memcached.redis相比很小巧,仅有不到8k行,而后三者大小分别为:60k,13k,86k 支持HTTP/1.1和CGI:採用IO复用实现,单线程,可移植:实现了基于URL的文件流量限制功能 特别适用于大量静态数据訪问的场景,如图片存储 2004年已经停止维护,有一个关于X-Forwarded-

GlusterFS源代码解析 —— GlusterFS 日志

Logging.c: /* Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> This file is part of GlusterFS. This file is licensed to you under your choice of the GNU Lesser General Public License, version 3 or any later version (LGPLv3 or later), or

Spark技术内幕:Client,Master和Worker 通信源代码解析

Spark的Cluster Manager能够有几种部署模式: Standlone Mesos YARN EC2 Local 在向集群提交计算任务后,系统的运算模型就是Driver Program定义的SparkContext向APP Master提交,有APP Master进行计算资源的调度并终于完毕计算.具体阐述能够阅读<Spark:大数据的电花火石!>. 那么Standalone模式下,Client.Master和Worker是怎样进行通信,注冊并开启服务的呢? 1. node之间的RP

linux device tree源代码解析--转

//Based on Linux v3.14 source code Linux设备树机制(Device Tree) 一.描述 ARM Device Tree起源于OpenFirmware (OF),在过去的Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx 中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备. resource.i2c_board_info.spi_board_info

实时捕捉以太网原始数据包(PacketRawEthernetMonitor)----Kithara RTS工程源代码解析

本文以windows实时拓展Kithara RTS安装目录下的smp文件夹内的PacketRawEthernetMonitor工程源码为例,该源码实现了一个简单的网络监视程序,可以实时监测网卡接收的原始数据.该工程主要使用了Kernel,Packet模块,有三个函数组成:主函数runSample,回调函数_callBack,线程_recvThread,_callBack和_recvThread之间存在着同步关系,线程_recvThread运行时会堵塞等待事件,回调函数设置该事件后线程才能继续运行

Asterisk 源代码解析之SIP呼叫

下图是asterisk的呼叫流程图: 我们以sip的呼叫过程为例来描述,其他channel的呼叫过程基本类似. Astersik下注册的sip用户主动发起一个呼叫的函数调用过程(incoming)如下: do_monitor->sipsock_read->handle_request->handle_request_invite->sip_new/ast_pbx_start->pbx_thread->__ast_pbx_run -> ast_spawn_exten

Android源代码解析之(十三)--&amp;gt;apk安装流程

转载请标明出处:一片枫叶的专栏 上一篇文章中给大家分析了一下android系统启动之后调用PackageManagerService服务并解析系统特定文件夹.解析apk文件并安装的过程,这个安装过程实际上是没有图形界面的,底层调用的是我们平时比較熟悉的adb命令,那么我们平时安装apk文件的时候大部分是都过图形界面安装的,那么这样的方式安装apk详细的流程是如何的呢? 本文我们就来详细看一下apk的详细安装过程,通过本文的学习希望帮助大家大概的了解到Android系统安装Apk文件的基本流程.好

Spring源代码解析

Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.iteye.com/topic/86594 Spring源代码解析(三):Spring JDBC:http://www.iteye.com/topic/87034 Spring源代码解析(四):Spring MVC:http://www.iteye.com/topic/87692 Spring源代码解析(五

Spring源代码解析(收藏)

Spring源代码解析(收藏)Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.iteye.com/topic/86594 Spring源代码解析(三):Spring JDBC:http://www.iteye.com/topic/87034 Spring源代码解析(四):Spring MVC:http://www.iteye.com/topic/8769