code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2009-2010 Ricardo Quesada
Copyright (c) 2011      Zynga Inc.

http://www.cocos2d-x.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "CCTMXLayer.h"
#include "CCTMXXMLParser.h"
#include "CCTMXTiledMap.h"
#include "CCSprite.h"
#include "CCTextureCache.h"
#include "CCPointExtension.h"
#include "support/data_support/ccCArray.h"
#include "CCDirector.h"

namespace cocos2d {

	// CCTMXLayer - init & alloc & dealloc
	CCTMXLayer * CCTMXLayer::layerWithTilesetInfo(CCTMXTilesetInfo *tilesetInfo, CCTMXLayerInfo *layerInfo, CCTMXMapInfo *mapInfo)
	{
		CCTMXLayer *pRet = new CCTMXLayer();
		if (pRet->initWithTilesetInfo(tilesetInfo, layerInfo, mapInfo))
		{
			pRet->autorelease();
			return pRet;
		}
		return NULL;
	}
	bool CCTMXLayer::initWithTilesetInfo(CCTMXTilesetInfo *tilesetInfo, CCTMXLayerInfo *layerInfo, CCTMXMapInfo *mapInfo)
	{
		// XXX: is 35% a good estimate ?
		CCSize size = layerInfo->m_tLayerSize;
		float totalNumberOfTiles = size.width * size.height;
		float capacity = totalNumberOfTiles * 0.35f + 1; // 35 percent is occupied ?

		CCTexture2D *texture = NULL;
		if( tilesetInfo )
		{
			texture = CCTextureCache::sharedTextureCache()->addImage(tilesetInfo->m_sSourceImage.c_str());
		}

		if (CCSpriteBatchNode::initWithTexture(texture, (unsigned int)capacity))
		{
			// layerInfo
			m_sLayerName = layerInfo->m_sName;
			m_tLayerSize = layerInfo->m_tLayerSize;
			m_pTiles = layerInfo->m_pTiles;
			m_uMinGID = layerInfo->m_uMinGID;
			m_uMaxGID = layerInfo->m_uMaxGID;
			m_cOpacity = layerInfo->m_cOpacity;
			m_pProperties = CCStringToStringDictionary::dictionaryWithDictionary(layerInfo->getProperties());
			m_fContentScaleFactor = CCDirector::sharedDirector()->getContentScaleFactor();

			// tilesetInfo
			m_pTileSet = tilesetInfo;
			CC_SAFE_RETAIN(m_pTileSet);

			// mapInfo
			m_tMapTileSize = mapInfo->getTileSize();
			m_uLayerOrientation = mapInfo->getOrientation();

			// offset (after layer orientation is set);
			CCPoint offset = this->calculateLayerOffset(layerInfo->m_tOffset);
			this->setPosition(offset);

			m_pAtlasIndexArray = ccCArrayNew((unsigned int)totalNumberOfTiles);

			this->setContentSizeInPixels(CCSizeMake(m_tLayerSize.width * m_tMapTileSize.width, m_tLayerSize.height * m_tMapTileSize.height));
                        m_tMapTileSize.width /= m_fContentScaleFactor;
                        m_tMapTileSize.height /= m_fContentScaleFactor;

			m_bUseAutomaticVertexZ = false;
			m_nVertexZvalue = 0;
			m_fAlphaFuncValue = 0;
			return true;
		}
		return false;
	}
	CCTMXLayer::CCTMXLayer()
        :m_tLayerSize(CCSizeZero)
        ,m_tMapTileSize(CCSizeZero)
        ,m_pTiles(NULL)
		,m_pTileSet(NULL)
		,m_pProperties(NULL)
        ,m_sLayerName("")
		,m_pReusedTile(NULL)
		,m_pAtlasIndexArray(NULL)
	{}
	CCTMXLayer::~CCTMXLayer()
	{
		CC_SAFE_RELEASE(m_pTileSet);
		CC_SAFE_RELEASE(m_pReusedTile);
		CC_SAFE_RELEASE(m_pProperties);

		if( m_pAtlasIndexArray )
		{
			ccCArrayFree(m_pAtlasIndexArray);
			m_pAtlasIndexArray = NULL;
		}

		CC_SAFE_DELETE_ARRAY(m_pTiles);
	}
	CCTMXTilesetInfo * CCTMXLayer::getTileSet()
	{
		return m_pTileSet;
	}
	void CCTMXLayer::setTileSet(CCTMXTilesetInfo* var)
	{
		CC_SAFE_RETAIN(var);
		CC_SAFE_RELEASE(m_pTileSet);
		m_pTileSet = var;
	}
	void CCTMXLayer::releaseMap()
	{
		if( m_pTiles )
		{
			delete [] m_pTiles;
			m_pTiles = NULL;
		}

		if( m_pAtlasIndexArray )
		{
			ccCArrayFree(m_pAtlasIndexArray);
			m_pAtlasIndexArray = NULL;
		}
	}

	// CCTMXLayer - setup Tiles
	void CCTMXLayer::setupTiles()
	{
		// Optimization: quick hack that sets the image size on the tileset
		m_pTileSet->m_tImageSize = m_pobTextureAtlas->getTexture()->getContentSizeInPixels();

		// By default all the tiles are aliased
		// pros:
		//  - easier to render
		// cons:
		//  - difficult to scale / rotate / etc.
		m_pobTextureAtlas->getTexture()->setAliasTexParameters();

		//CFByteOrder o = CFByteOrderGetCurrent();

		// Parse cocos2d properties
		this->parseInternalProperties();

		for( unsigned int y=0; y < m_tLayerSize.height; y++ )
		{
			for( unsigned int x=0; x < m_tLayerSize.width; x++ )
			{
				unsigned int pos = (unsigned int)(x + m_tLayerSize.width * y);
				unsigned int gid = m_pTiles[ pos ];

				// gid are stored in little endian.
				// if host is big endian, then swap
				//if( o == CFByteOrderBigEndian )
				//	gid = CFSwapInt32( gid );
				/* We support little endian.*/

				// XXX: gid == 0 --> empty tile
				if( gid != 0 )
				{
					this->appendTileForGID(gid, ccp((float)x, (float)y));

					// Optimization: update min and max GID rendered by the layer
					m_uMinGID = MIN(gid, m_uMinGID);
					m_uMaxGID = MAX(gid, m_uMaxGID);
				}
			}
		}

		CCAssert( m_uMaxGID >= m_pTileSet->m_uFirstGid &&
			m_uMinGID >= m_pTileSet->m_uFirstGid, "TMX: Only 1 tilset per layer is supported");
	}

	// CCTMXLayer - Properties
	CCString *CCTMXLayer::propertyNamed(const char *propertyName)
	{
		return m_pProperties->objectForKey(std::string(propertyName));
	}
	void CCTMXLayer::parseInternalProperties()
	{
		// if cc_vertex=automatic, then tiles will be rendered using vertexz

		CCString *vertexz = propertyNamed("cc_vertexz");
		if( vertexz )
		{
			if( vertexz->m_sString == "automatic" )
			{
				m_bUseAutomaticVertexZ = true;
			}
			else
			{
				m_nVertexZvalue = vertexz->toInt();
			}
		}

		CCString *alphaFuncVal = propertyNamed("cc_alpha_func");
		if (alphaFuncVal)
		{
			m_fAlphaFuncValue = alphaFuncVal->toFloat();
		}
	}

	// CCTMXLayer - obtaining tiles/gids
	CCSprite * CCTMXLayer::tileAt(const CCPoint& pos)
	{
		CCAssert( pos.x < m_tLayerSize.width && pos.y < m_tLayerSize.height && pos.x >=0 && pos.y >=0, "TMXLayer: invalid position");
		CCAssert( m_pTiles && m_pAtlasIndexArray, "TMXLayer: the tiles map has been released");

		CCSprite *tile = NULL;
		unsigned int gid = this->tileGIDAt(pos);

		// if GID == 0, then no tile is present
		if( gid )
		{
			int z = (int)(pos.x + pos.y * m_tLayerSize.width);
			tile = (CCSprite*) this->getChildByTag(z);

			// tile not created yet. create it
			if( ! tile )
			{
				CCRect rect = m_pTileSet->rectForGID(gid);
                                rect = CCRectMake(rect.origin.x / m_fContentScaleFactor, rect.origin.y / m_fContentScaleFactor, rect.size.width/ m_fContentScaleFactor, rect.size.height/ m_fContentScaleFactor);

				tile = new CCSprite();
				tile->initWithBatchNode(this, rect);
				tile->setPosition(positionAt(pos));
				tile->setVertexZ((float)vertexZForPos(pos));
				tile->setAnchorPoint(CCPointZero);
				tile->setOpacity(m_cOpacity);

				unsigned int indexForZ = atlasIndexForExistantZ(z);
				this->addSpriteWithoutQuad(tile, indexForZ, z);
				tile->release();
			}
		}
		return tile;
	}
	unsigned int CCTMXLayer::tileGIDAt(const CCPoint& pos)
	{
		CCAssert( pos.x < m_tLayerSize.width && pos.y < m_tLayerSize.height && pos.x >=0 && pos.y >=0, "TMXLayer: invalid position");
		CCAssert( m_pTiles && m_pAtlasIndexArray, "TMXLayer: the tiles map has been released");

		int idx = (int)(pos.x + pos.y * m_tLayerSize.width);
		return m_pTiles[ idx ];
	}

	// CCTMXLayer - adding helper methods
	CCSprite * CCTMXLayer::insertTileForGID(unsigned int gid, const CCPoint& pos)
	{
		CCRect rect = m_pTileSet->rectForGID(gid);
                rect = CCRectMake(rect.origin.x / m_fContentScaleFactor, rect.origin.y / m_fContentScaleFactor, rect.size.width/ m_fContentScaleFactor, rect.size.height/ m_fContentScaleFactor);

		int z = (int)(pos.x + pos.y * m_tLayerSize.width);

		if( ! m_pReusedTile )
		{
			m_pReusedTile = new CCSprite();
			m_pReusedTile->initWithBatchNode(this, rect);
		}
		else
		{
			m_pReusedTile->initWithBatchNode(this, rect);
		}
		m_pReusedTile->setPositionInPixels(positionAt(pos));
		m_pReusedTile->setVertexZ((float)vertexZForPos(pos));
		m_pReusedTile->setAnchorPoint(CCPointZero);
		m_pReusedTile->setOpacity(m_cOpacity);

		// get atlas index
		unsigned int indexForZ = atlasIndexForNewZ(z);

		// Optimization: add the quad without adding a child
		this->addQuadFromSprite(m_pReusedTile, indexForZ);

		// insert it into the local atlasindex array
		ccCArrayInsertValueAtIndex(m_pAtlasIndexArray, (void*)z, indexForZ);

		// update possible children
		if (m_pChildren && m_pChildren->count()>0)
		{
            CCObject* pObject = NULL;
            CCARRAY_FOREACH(m_pChildren, pObject)
            {
                CCSprite* pChild = (CCSprite*) pObject;
                if (pChild)
                {
                    unsigned int ai = pChild->getAtlasIndex();
                    if ( ai >= indexForZ )
                    {
                        pChild->setAtlasIndex(ai+1);
                    }
                }
            }
		}
		m_pTiles[z] = gid;
		return m_pReusedTile;
	}
	CCSprite * CCTMXLayer::updateTileForGID(unsigned int gid, const CCPoint& pos)
	{
		CCRect rect = m_pTileSet->rectForGID(gid);
                rect = CCRectMake(rect.origin.x / m_fContentScaleFactor, rect.origin.y / m_fContentScaleFactor, rect.size.width/ m_fContentScaleFactor, rect.size.height/ m_fContentScaleFactor);
		int z = (int)(pos.x + pos.y * m_tLayerSize.width);

		if( ! m_pReusedTile )
		{
			m_pReusedTile = new CCSprite();
			m_pReusedTile->initWithBatchNode(this, rect);
		}
		else
		{
			m_pReusedTile->initWithBatchNode(this, rect);
		}

		m_pReusedTile->setPositionInPixels(positionAt(pos));
		m_pReusedTile->setVertexZ((float)vertexZForPos(pos));
		m_pReusedTile->setAnchorPoint(CCPointZero);
		m_pReusedTile->setOpacity(m_cOpacity);

		// get atlas index
		unsigned int indexForZ = atlasIndexForExistantZ(z);
		m_pReusedTile->setAtlasIndex(indexForZ);
        m_pReusedTile->setDirty(true);
		m_pReusedTile->updateTransform();
		m_pTiles[z] = gid;

		return m_pReusedTile;
	}

	// used only when parsing the map. useless after the map was parsed
	// since lot's of assumptions are no longer true
	CCSprite * CCTMXLayer::appendTileForGID(unsigned int gid, const CCPoint& pos)
	{
		CCRect rect = m_pTileSet->rectForGID(gid);
                rect = CCRectMake(rect.origin.x / m_fContentScaleFactor, rect.origin.y / m_fContentScaleFactor, rect.size.width/ m_fContentScaleFactor, rect.size.height/ m_fContentScaleFactor);

		int z = (int)(pos.x + pos.y * m_tLayerSize.width);

		if( ! m_pReusedTile )
		{
			m_pReusedTile = new CCSprite();
			m_pReusedTile->initWithBatchNode(this, rect);
		}
		else
		{
			m_pReusedTile->initWithBatchNode(this, rect);
		}

		m_pReusedTile->setPosition(positionAt(pos));
		m_pReusedTile->setVertexZ((float)vertexZForPos(pos));
		m_pReusedTile->setAnchorPoint(CCPointZero);
		m_pReusedTile->setOpacity(m_cOpacity);

		// optimization:
		// The difference between appendTileForGID and insertTileforGID is that append is faster, since
		// it appends the tile at the end of the texture atlas
		unsigned int indexForZ = m_pAtlasIndexArray->num;

		// don't add it using the "standard" way.
		addQuadFromSprite(m_pReusedTile, indexForZ);

		// append should be after addQuadFromSprite since it modifies the quantity values
		ccCArrayInsertValueAtIndex(m_pAtlasIndexArray, (void*)z, indexForZ);

		return m_pReusedTile;
	}

	// CCTMXLayer - atlasIndex and Z
	static inline int compareInts(const void * a, const void * b)
	{
		return ( *(int*)a - *(int*)b );
	}
	unsigned int CCTMXLayer::atlasIndexForExistantZ(unsigned int z)
	{
		int key=z;
		int *item = (int*)bsearch((void*)&key, (void*)&m_pAtlasIndexArray->arr[0], m_pAtlasIndexArray->num, sizeof(void*), compareInts);

		CCAssert( item, "TMX atlas index not found. Shall not happen");

        int index = ((size_t)item - (size_t)m_pAtlasIndexArray->arr) / sizeof(void*);
		return index;
	}
	unsigned int CCTMXLayer::atlasIndexForNewZ(int z)
	{
		// XXX: This can be improved with a sort of binary search
		unsigned int i=0;
		for( i=0; i< m_pAtlasIndexArray->num ; i++)
		{
            int val = (size_t) m_pAtlasIndexArray->arr[i];
			if( z < val )
				break;
		}
		return i;
	}

	// CCTMXLayer - adding / remove tiles
	void CCTMXLayer::setTileGID(unsigned int gid, const CCPoint& pos)
	{
		CCAssert( pos.x < m_tLayerSize.width && pos.y < m_tLayerSize.height && pos.x >=0 && pos.y >=0, "TMXLayer: invalid position");
		CCAssert( m_pTiles && m_pAtlasIndexArray, "TMXLayer: the tiles map has been released");
        CCAssert( gid == 0 || gid >= m_pTileSet->m_uFirstGid, "TMXLayer: invalid gid" );

		unsigned int currentGID = tileGIDAt(pos);

		if( currentGID != gid )
		{
			// 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(gid, pos);
			}

			// modifying an existing tile with a non-empty tile
			else
			{
				unsigned int z = (unsigned int)(pos.x + pos.y * m_tLayerSize.width);
				CCSprite *sprite = (CCSprite*)getChildByTag(z);
				if( sprite )
				{
					CCRect rect = m_pTileSet->rectForGID(gid);
                                        rect = CCRectMake(rect.origin.x / m_fContentScaleFactor, rect.origin.y / m_fContentScaleFactor, rect.size.width/ m_fContentScaleFactor, rect.size.height/ m_fContentScaleFactor);

					sprite->setTextureRectInPixels(rect, false, rect.size);
					m_pTiles[z] = gid;
				}
				else
				{
					updateTileForGID(gid, pos);
				}
			}
		}
	}
	void CCTMXLayer::addChild(CCNode * child, int zOrder, int tag)
	{
        CC_UNUSED_PARAM(child);
        CC_UNUSED_PARAM(zOrder);
        CC_UNUSED_PARAM(tag);
		CCAssert(0, "addChild: is not supported on CCTMXLayer. Instead use setTileGID:at:/tileAt:");
	}
	void CCTMXLayer::removeChild(CCNode* node, bool cleanup)
	{
		CCSprite *sprite = (CCSprite*)node;
		// allows removing nil objects
		if( ! sprite )
			return;

		CCAssert( m_pChildren->containsObject(sprite), "Tile does not belong to TMXLayer");

		unsigned int atlasIndex = sprite->getAtlasIndex();
        unsigned int zz = (size_t) m_pAtlasIndexArray->arr[atlasIndex];
		m_pTiles[zz] = 0;
		ccCArrayRemoveValueAtIndex(m_pAtlasIndexArray, atlasIndex);
		CCSpriteBatchNode::removeChild(sprite, cleanup);
	}
	void CCTMXLayer::removeTileAt(const CCPoint& pos)
	{
		CCAssert( pos.x < m_tLayerSize.width && pos.y < m_tLayerSize.height && pos.x >=0 && pos.y >=0, "TMXLayer: invalid position");
		CCAssert( m_pTiles && m_pAtlasIndexArray, "TMXLayer: the tiles map has been released");

		unsigned int gid = tileGIDAt(pos);

		if( gid )
		{
			unsigned int z = (unsigned int)(pos.x + pos.y * m_tLayerSize.width);
			unsigned int atlasIndex = atlasIndexForExistantZ(z);

			// remove tile from GID map
			m_pTiles[z] = 0;

			// remove tile from atlas position array
			ccCArrayRemoveValueAtIndex(m_pAtlasIndexArray, atlasIndex);

			// remove it from sprites and/or texture atlas
			CCSprite *sprite = (CCSprite*)getChildByTag(z);
			if( sprite )
			{
				CCSpriteBatchNode::removeChild(sprite, true);
			}
			else
			{
				m_pobTextureAtlas->removeQuadAtIndex(atlasIndex);

				// update possible children
				if (m_pChildren && m_pChildren->count()>0)
				{
                    CCObject* pObject = NULL;
                    CCARRAY_FOREACH(m_pChildren, pObject)
                    {
                        CCSprite* pChild = (CCSprite*) pObject;
                        if (pChild)
                        {
                            unsigned int ai = pChild->getAtlasIndex();
                            if ( ai >= atlasIndex )
                            {
                                pChild->setAtlasIndex(ai-1);
                            }
                        }
                    }
				}
			}
		}
	}

	//CCTMXLayer - obtaining positions, offset
	CCPoint CCTMXLayer::calculateLayerOffset(const CCPoint& pos)
	{
		CCPoint ret = CCPointZero;
		switch( m_uLayerOrientation )
		{
		case CCTMXOrientationOrtho:
			ret = ccp( pos.x * m_tMapTileSize.width, -pos.y *m_tMapTileSize.height);
			break;
		case CCTMXOrientationIso:
			ret = ccp( (m_tMapTileSize.width /2) * (pos.x - pos.y),
				(m_tMapTileSize.height /2 ) * (-pos.x - pos.y) );
			break;
		case CCTMXOrientationHex:
			CCAssert(CCPoint::CCPointEqualToPoint(pos, CCPointZero), "offset for hexagonal map not implemented yet");
			break;
		}
		return ret;
	}
	CCPoint CCTMXLayer::positionAt(const CCPoint& pos)
	{
		CCPoint ret = CCPointZero;
		switch( m_uLayerOrientation )
		{
		case CCTMXOrientationOrtho:
			ret = positionForOrthoAt(pos);
			break;
		case CCTMXOrientationIso:
			ret = positionForIsoAt(pos);
			break;
		case CCTMXOrientationHex:
			ret = positionForHexAt(pos);
			break;
		}
		return ret;
	}
	CCPoint CCTMXLayer::positionForOrthoAt(const CCPoint& pos)
	{
        CCPoint xy = CCPointMake(pos.x * m_tMapTileSize.width,
                                (m_tLayerSize.height - pos.y - 1) * m_tMapTileSize.height);
        return xy;
	}
	CCPoint CCTMXLayer::positionForIsoAt(const CCPoint& pos)
	{
        CCPoint xy = CCPointMake(m_tMapTileSize.width /2 * ( m_tLayerSize.width + pos.x - pos.y - 1),
                                 m_tMapTileSize.height /2 * (( m_tLayerSize.height * 2 - pos.x - pos.y) - 2));
        return xy;
	}
	CCPoint CCTMXLayer::positionForHexAt(const CCPoint& pos)
	{
		float diffY = 0;
		if( (int)pos.x % 2 == 1 )
		{
			diffY = -m_tMapTileSize.height/2 ;
		}

        CCPoint xy = CCPointMake(pos.x * m_tMapTileSize.width*3/4,
                                (m_tLayerSize.height - pos.y - 1) * m_tMapTileSize.height + diffY);
        return xy;
	}
	int CCTMXLayer::vertexZForPos(const CCPoint& pos)
	{
		int ret = 0;
		unsigned int maxVal = 0;
		if( m_bUseAutomaticVertexZ )
		{
			switch( m_uLayerOrientation )
			{
			case CCTMXOrientationIso:
				maxVal = (unsigned int)(m_tLayerSize.width + m_tLayerSize.height);
				ret = (int)(-(maxVal - (pos.x + pos.y)));
				break;
			case CCTMXOrientationOrtho:
				ret = (int)(-(m_tLayerSize.height-pos.y));
				break;
			case CCTMXOrientationHex:
				CCAssert(0, "TMX Hexa zOrder not supported");
				break;
			default:
				CCAssert(0, "TMX invalid value");
				break;
			}
		}
		else
		{
			ret = m_nVertexZvalue;
		}
		return ret;
	}

	// CCTMXLayer - draw
	void CCTMXLayer::draw()
	{
		if( m_bUseAutomaticVertexZ )
		{
			glEnable(GL_ALPHA_TEST);
			glAlphaFunc(GL_GREATER, m_fAlphaFuncValue);
		}

		CCSpriteBatchNode::draw();

		if( m_bUseAutomaticVertexZ )
		{
			glDisable(GL_ALPHA_TEST);
		}
	}

	CCStringToStringDictionary * CCTMXLayer::getProperties()
	{
		return m_pProperties;
	}
	void CCTMXLayer::setProperties(CCStringToStringDictionary* var)
	{
		CC_SAFE_RETAIN(var);
		CC_SAFE_RELEASE(m_pProperties);
		m_pProperties = var;
	}

}// namespace cocos2d


code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2010      Neophit
Copyright (c) 2010      Ricardo Quesada
Copyright (c) 2011      Zynga Inc.

http://www.cocos2d-x.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "CCTMXObjectGroup.h"
#include "ccMacros.h"
namespace cocos2d {

	//implementation CCTMXObjectGroup

	CCTMXObjectGroup::CCTMXObjectGroup()
        :m_tPositionOffset(CCPointZero)
		,m_sGroupName("")
	{
		m_pObjects = new CCMutableArray<CCStringToStringDictionary*>();
		m_pProperties = new CCStringToStringDictionary();
	}
	CCTMXObjectGroup::~CCTMXObjectGroup()
	{
		CCLOGINFO( "cocos2d: deallocing.");
		CC_SAFE_RELEASE(m_pObjects);
		CC_SAFE_RELEASE(m_pProperties);
	}
	CCStringToStringDictionary * CCTMXObjectGroup::objectNamed(const char *objectName)
	{
		if (m_pObjects && m_pObjects->count() > 0)
		{
			CCMutableArray<CCStringToStringDictionary*>::CCMutableArrayIterator it;
			for (it = m_pObjects->begin(); it != m_pObjects->end(); ++it)
			{
				CCString *name = (*it)->objectForKey(std::string("name"));
				if (name && name->m_sString == objectName)
				{
					return *it;
				}
			}
		}
		// object not found
		return NULL;
	}
	CCString *CCTMXObjectGroup::propertyNamed(const char* propertyName)
	{
		return m_pProperties->objectForKey(std::string(propertyName));
	}

	CCStringToStringDictionary * CCTMXObjectGroup::getProperties()
	{
		return m_pProperties;
	}
	void CCTMXObjectGroup::setProperties(CCStringToStringDictionary * properties)
	{
		CC_SAFE_RETAIN(properties);
		CC_SAFE_RELEASE(m_pProperties);
		m_pProperties = properties;
	}
	CCMutableArray<CCStringToStringDictionary*> *CCTMXObjectGroup::getObjects()
	{
		return m_pObjects;
	}
	void CCTMXObjectGroup::setObjects(CCMutableArray<CCStringToStringDictionary*> * objects)
	{
		CC_SAFE_RETAIN(objects);
		CC_SAFE_RELEASE(m_pObjects);
		m_pObjects = objects;
	}

}// namespace cocos2d

license: mit


code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2009-2010 Ricardo Quesada
Copyright (c) 2011      Zynga Inc.

http://www.cocos2d-x.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "CCTMXTiledMap.h"
#include "CCTMXXMLParser.h"
#include "CCTMXLayer.h"
#include "CCSprite.h"
#include "CCPointExtension.h"

namespace cocos2d{

	// implementation CCTMXTiledMap
	CCTMXTiledMap * CCTMXTiledMap::tiledMapWithTMXFile(const char *tmxFile)
	{
		CCTMXTiledMap *pRet = new CCTMXTiledMap();
		if (pRet->initWithTMXFile(tmxFile))
		{
			pRet->autorelease();
			return pRet;
		}
        CC_SAFE_DELETE(pRet);
		return NULL;
	}
	bool CCTMXTiledMap::initWithTMXFile(const char *tmxFile)
	{
		CCAssert(tmxFile != NULL && strlen(tmxFile)>0, "TMXTiledMap: tmx file should not bi nil");

		setContentSize(CCSizeZero);

		CCTMXMapInfo *mapInfo = CCTMXMapInfo::formatWithTMXFile(tmxFile);

        if (! mapInfo)
        {
            return false;
        }
		CCAssert( mapInfo->getTilesets()->count() != 0, "TMXTiledMap: Map not found. Please check the filename.");

		m_tMapSize = mapInfo->getMapSize();
		m_tTileSize = mapInfo->getTileSize();
		m_nMapOrientation = mapInfo->getOrientation();
		setObjectGroups(mapInfo->getObjectGroups());
		setProperties(mapInfo->getProperties());
		CC_SAFE_RELEASE(m_pTileProperties);
		m_pTileProperties = mapInfo->getTileProperties();
		CC_SAFE_RETAIN(m_pTileProperties);

		int idx = 0;

		CCMutableArray<CCTMXLayerInfo*>* layers = mapInfo->getLayers();
		if (layers && layers->count()>0)
		{
            if (NULL == m_pTMXLayers)
            {
                m_pTMXLayers = new CCDictionary<std::string, CCTMXLayer*>();
                CCAssert(m_pTMXLayers, "Allocate memory failed!");
            }

			CCTMXLayerInfo *layerInfo = NULL;
			CCMutableArray<CCTMXLayerInfo*>::CCMutableArrayIterator it;
			for (it = layers->begin(); it != layers->end(); ++it)
			{
				layerInfo = *it;
				if (layerInfo && layerInfo->m_bVisible)
				{
					CCTMXLayer *child = parseLayer(layerInfo, mapInfo);
					addChild((CCNode*)child, idx, idx);

                    // record the CCTMXLayer object by it's name
                    std::string layerName = child->getLayerName();
                    m_pTMXLayers->setObject(child, layerName);

					// 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++;
				}
			}
		}
		return true;
	}
	CCTMXTiledMap::CCTMXTiledMap()
        :m_tMapSize(CCSizeZero)
		,m_tTileSize(CCSizeZero)
		,m_pObjectGroups(NULL)
		,m_pProperties(NULL)
		,m_pTileProperties(NULL)
        ,m_pTMXLayers(NULL)
	{
	}
	CCTMXTiledMap::~CCTMXTiledMap()
	{
		CC_SAFE_RELEASE(m_pProperties);
		CC_SAFE_RELEASE(m_pObjectGroups);
		CC_SAFE_RELEASE(m_pTileProperties);
        CC_SAFE_RELEASE(m_pTMXLayers);
	}
	CCMutableArray<CCTMXObjectGroup*> * CCTMXTiledMap::getObjectGroups()
	{
		return m_pObjectGroups;
	}
	void CCTMXTiledMap::setObjectGroups(CCMutableArray<CCTMXObjectGroup*>* var)
	{
		CC_SAFE_RETAIN(var);
		CC_SAFE_RELEASE(m_pObjectGroups);
		m_pObjectGroups = var;
	}
	CCStringToStringDictionary * CCTMXTiledMap::getProperties()
	{
		return m_pProperties;
	}
	void CCTMXTiledMap::setProperties(CCStringToStringDictionary* var)
	{
		CC_SAFE_RETAIN(var);
		CC_SAFE_RELEASE(m_pProperties);
		m_pProperties = var;
	}
	// private
	CCTMXLayer * CCTMXTiledMap::parseLayer(CCTMXLayerInfo *layerInfo, CCTMXMapInfo *mapInfo)
	{
		CCTMXTilesetInfo *tileset = tilesetForLayer(layerInfo, mapInfo);
		CCTMXLayer *layer = CCTMXLayer::layerWithTilesetInfo(tileset, layerInfo, mapInfo);

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

		return layer;
	}

	CCTMXTilesetInfo * CCTMXTiledMap::tilesetForLayer(CCTMXLayerInfo *layerInfo, CCTMXMapInfo *mapInfo)
	{
		CCSize size = layerInfo->m_tLayerSize;
		CCMutableArray<CCTMXTilesetInfo*>* tilesets = mapInfo->getTilesets();
		if (tilesets && tilesets->count()>0)
		{
			CCTMXTilesetInfo *tileset = NULL;
			CCMutableArray<CCTMXTilesetInfo*>::CCMutableArrayRevIterator rit;
			for (rit = tilesets->rbegin(); rit != tilesets->rend(); ++rit)
			{
				tileset = *rit;
				if (tileset)
				{
					for( unsigned int y=0; y < size.height; y++ )
					{
						for( unsigned int x=0; x < size.width; x++ )
						{
							unsigned int pos = (unsigned int)(x + size.width * y);
							unsigned int gid = layerInfo->m_pTiles[ pos ];

							// gid are stored in little endian.
							// if host is big endian, then swap
							//if( o == CFByteOrderBigEndian )
							//	gid = CFSwapInt32( gid );
							/* We support little endian.*/

							// XXX: gid == 0 --> empty tile
							if( gid != 0 )
							{
								// Optimization: quick return
								// if the layer is invalid (more than 1 tileset per layer) an CCAssert will be thrown later
								if( gid >= tileset->m_uFirstGid )
									return tileset;
							}
						}
					}
				}
			}
		}

		// If all the tiles are 0, return empty tileset
		CCLOG("cocos2d: Warning: TMX Layer '%s' has no tiles", layerInfo->m_sName.c_str());
		return NULL;
	}

	// public
	CCTMXLayer * CCTMXTiledMap::layerNamed(const char *layerName)
	{
		std::string sLayerName = layerName;
        CCTMXLayer * pRet = m_pTMXLayers->objectForKey(sLayerName);
		return pRet;
	}
	CCTMXObjectGroup * CCTMXTiledMap::objectGroupNamed(const char *groupName)
	{
		std::string sGroupName = groupName;
		if (m_pObjectGroups && m_pObjectGroups->count()>0)
		{
			CCTMXObjectGroup *objectGroup;
			CCMutableArray<CCTMXObjectGroup*>::CCMutableArrayIterator it;
			for (it = m_pObjectGroups->begin(); it != m_pObjectGroups->end(); ++it)
			{
				objectGroup = (CCTMXObjectGroup*)(*it);
				if (objectGroup && objectGroup->getGroupName() == sGroupName)
				{
					return objectGroup;
				}
			}
		}

		// objectGroup not found
		return NULL;
	}

	CCString * CCTMXTiledMap::propertyNamed(const char *propertyName)
	{
		return m_pProperties->objectForKey(std::string(propertyName));
	}
	CCDictionary<std::string, CCString*> * CCTMXTiledMap::propertiesForGID(int GID)
	{
		return m_pTileProperties->objectForKey(GID);
	}

}// namespace cocos2d


code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2011		Максим Аксенов
Copyright (c) 2009-2010 Ricardo Quesada
Copyright (c) 2011      Zynga Inc.

http://www.cocos2d-x.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/

#include <map>
#include "CCTMXXMLParser.h"
#include "CCTMXTiledMap.h"
#include "ccMacros.h"
#include "CCFileUtils.h"
#include "support/zip_support/ZipUtils.h"
#include "CCPointExtension.h"
#include "support/base64.h"
#include "platform/platform.h"

/*
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE)
	#include "expat.h"
#else
	#include <libxml/parser.h>
	#include <libxml/tree.h>
	#include <libxml/xmlmemory.h>
	#include "CCLibxml2.h"
#endf
*/

namespace cocos2d {

	/*
	void tmx_startElement(void *ctx, const xmlChar *name, const xmlChar **atts);
	void tmx_endElement(void *ctx, const xmlChar *name);
	void tmx_characters(void *ctx, const xmlChar *ch, int len);
	*/

	static const char* valueForKey(const char *key, std::map<std::string, std::string>* dict)
	{
		if (dict)
		{
			std::map<std::string, std::string>::iterator it = dict->find(key);
			return it!=dict->end() ? it->second.c_str() : "";
		}
		return "";
	}
	// implementation CCTMXLayerInfo
	CCTMXLayerInfo::CCTMXLayerInfo()
        : m_sName("")
        , m_pTiles(NULL)
		, m_bOwnTiles(true)
		, m_uMinGID(100000)
		, m_uMaxGID(0)
		, m_tOffset(CCPointZero)
	{
		m_pProperties= new CCStringToStringDictionary();;
	}
	CCTMXLayerInfo::~CCTMXLayerInfo()
	{
		CCLOGINFO("cocos2d: deallocing.");
		CC_SAFE_RELEASE(m_pProperties);
		if( m_bOwnTiles && m_pTiles )
		{
			delete [] m_pTiles;
			m_pTiles = NULL;
		}
	}
	CCStringToStringDictionary * CCTMXLayerInfo::getProperties()
	{
		return m_pProperties;
	}
	void CCTMXLayerInfo::setProperties(CCStringToStringDictionary* var)
	{
		CC_SAFE_RETAIN(var);
		CC_SAFE_RELEASE(m_pProperties);
		m_pProperties = var;
	}

	// implementation CCTMXTilesetInfo
	CCTMXTilesetInfo::CCTMXTilesetInfo()
		:m_uFirstGid(0)
		,m_tTileSize(CCSizeZero)
		,m_uSpacing(0)
		,m_uMargin(0)
		,m_tImageSize(CCSizeZero)
	{
	}
	CCTMXTilesetInfo::~CCTMXTilesetInfo()
	{
		CCLOGINFO("cocos2d: deallocing.");
	}
	CCRect CCTMXTilesetInfo::rectForGID(unsigned int gid)
	{
		CCRect rect;
		rect.size = m_tTileSize;
		gid = gid - m_uFirstGid;
		int max_x = (int)((m_tImageSize.width - m_uMargin*2 + m_uSpacing) / (m_tTileSize.width + m_uSpacing));
		//	int max_y = (imageSize.height - margin*2 + spacing) / (tileSize.height + spacing);
		rect.origin.x = (gid % max_x) * (m_tTileSize.width + m_uSpacing) + m_uMargin;
		rect.origin.y = (gid / max_x) * (m_tTileSize.height + m_uSpacing) + m_uMargin;
		return rect;
	}

	// implementation CCTMXMapInfo

	CCTMXMapInfo * CCTMXMapInfo::formatWithTMXFile(const char *tmxFile)
	{
		CCTMXMapInfo *pRet = new CCTMXMapInfo();
		if(pRet->initWithTMXFile(tmxFile))
		{
			pRet->autorelease();
			return pRet;
		}
		CC_SAFE_DELETE(pRet);
		return NULL;
	}
	bool CCTMXMapInfo::initWithTMXFile(const char *tmxFile)
	{
		m_pTilesets = new CCMutableArray<CCTMXTilesetInfo*>();
		m_pLayers = new CCMutableArray<CCTMXLayerInfo*>();
		m_sTMXFileName = CCFileUtils::fullPathFromRelativePath(tmxFile);
		m_pObjectGroups = new CCMutableArray<CCTMXObjectGroup*>();
		m_pProperties = new CCStringToStringDictionary();
		m_pTileProperties = new CCDictionary<int, CCStringToStringDictionary*>();

		// tmp vars
		m_sCurrentString = "";
		m_bStoringCharacters = false;
		m_nLayerAttribs = TMXLayerAttribNone;
		m_nParentElement = TMXPropertyNone;

		return parseXMLFile(m_sTMXFileName.c_str());
	}
	CCTMXMapInfo::CCTMXMapInfo()
        :m_tMapSize(CCSizeZero)
        ,m_tTileSize(CCSizeZero)
        ,m_pLayers(NULL)
        ,m_pTilesets(NULL)
        ,m_pObjectGroups(NULL)
        ,m_nLayerAttribs(0)
        ,m_bStoringCharacters(false)
		,m_pProperties(NULL)
		,m_pTileProperties(NULL)
	{
	}
	CCTMXMapInfo::~CCTMXMapInfo()
	{
		CCLOGINFO("cocos2d: deallocing.");
		CC_SAFE_RELEASE(m_pTilesets);
		CC_SAFE_RELEASE(m_pLayers);
		CC_SAFE_RELEASE(m_pProperties);
		CC_SAFE_RELEASE(m_pTileProperties);
		CC_SAFE_RELEASE(m_pObjectGroups);
	}
	CCMutableArray<CCTMXLayerInfo*> * CCTMXMapInfo::getLayers()
	{
		return m_pLayers;
	}
	void CCTMXMapInfo::setLayers(CCMutableArray<CCTMXLayerInfo*>* var)
	{
		CC_SAFE_RETAIN(var);
		CC_SAFE_RELEASE(m_pLayers);
		m_pLayers = var;
	}
	CCMutableArray<CCTMXTilesetInfo*> * CCTMXMapInfo::getTilesets()
	{
		return m_pTilesets;
	}
	void CCTMXMapInfo::setTilesets(CCMutableArray<CCTMXTilesetInfo*>* var)
	{
		CC_SAFE_RETAIN(var);
		CC_SAFE_RELEASE(m_pTilesets);
		m_pTilesets = var;
	}
	CCMutableArray<CCTMXObjectGroup*> * CCTMXMapInfo::getObjectGroups()
	{
		return m_pObjectGroups;
	}
	void CCTMXMapInfo::setObjectGroups(CCMutableArray<CCTMXObjectGroup*>* var)
	{
		CC_SAFE_RETAIN(var);
		CC_SAFE_RELEASE(m_pObjectGroups);
		m_pObjectGroups = var;
	}
	CCStringToStringDictionary * CCTMXMapInfo::getProperties()
	{
		return m_pProperties;
	}
	void CCTMXMapInfo::setProperties(CCStringToStringDictionary* var)
	{
		CC_SAFE_RETAIN(var);
		CC_SAFE_RELEASE(m_pProperties);
		m_pProperties = var;
	}
	CCDictionary<int, CCStringToStringDictionary*> * CCTMXMapInfo::getTileProperties()
	{
		return m_pTileProperties;
	}
	void CCTMXMapInfo::setTileProperties(CCDictionary<int, CCStringToStringDictionary*> * tileProperties)
	{
		CC_SAFE_RETAIN(tileProperties);
		CC_SAFE_RELEASE(m_pTileProperties);
		m_pTileProperties = tileProperties;
	}

	bool CCTMXMapInfo::parseXMLFile(const char *xmlFilename)
	{
		CCSAXParser parser;

		if (false == parser.init("UTF-8") )
		{
			return false;
		}

		parser.setDelegator(this);

		return parser.parse(xmlFilename);;
	}

	// the XML parser calls here with all the elements
	void CCTMXMapInfo::startElement(void *ctx, const char *name, const char **atts)
	{
        CC_UNUSED_PARAM(ctx);
		CCTMXMapInfo *pTMXMapInfo = this;
		std::string elementName = (char*)name;
		std::map<std::string, std::string> *attributeDict = new std::map<std::string, std::string>();
		if(atts && atts[0])
		{
			for(int i = 0; atts[i]; i += 2)
			{
				std::string key = (char*)atts[i];
				std::string value = (char*)atts[i+1];
				attributeDict->insert(pair<std::string, std::string>(key, value));
			}
		}
		if(elementName == "map")
		{
			std::string version = valueForKey("version", attributeDict);
			if ( version != "1.0")
			{
				CCLOG("cocos2d: TMXFormat: Unsupported TMX version: %s", version.c_str());
			}
			std::string orientationStr = valueForKey("orientation", attributeDict);
			if( orientationStr == "orthogonal")
				pTMXMapInfo->setOrientation(CCTMXOrientationOrtho);
			else if ( orientationStr  == "isometric")
				pTMXMapInfo->setOrientation(CCTMXOrientationIso);
			else if( orientationStr == "hexagonal")
				pTMXMapInfo->setOrientation(CCTMXOrientationHex);
			else
				CCLOG("cocos2d: TMXFomat: Unsupported orientation: %d", pTMXMapInfo->getOrientation());

			CCSize s;
			s.width = (float)atof(valueForKey("width", attributeDict));
			s.height = (float)atof(valueForKey("height", attributeDict));
			pTMXMapInfo->setMapSize(s);

			s.width = (float)atof(valueForKey("tilewidth", attributeDict));
			s.height = (float)atof(valueForKey("tileheight", attributeDict));
			pTMXMapInfo->setTileSize(s);

			// The parent element is now "map"
			pTMXMapInfo->setParentElement(TMXPropertyMap);
		}
		else if(elementName == "tileset")
		{
			// If this is an external tileset then start parsing that
			std::string externalTilesetFilename = valueForKey("source", attributeDict);
			if (externalTilesetFilename != "")
			{
				externalTilesetFilename = CCFileUtils::fullPathFromRelativeFile(externalTilesetFilename.c_str(), pTMXMapInfo->getTMXFileName());
				pTMXMapInfo->parseXMLFile(externalTilesetFilename.c_str());
			}
			else
			{
				CCTMXTilesetInfo *tileset = new CCTMXTilesetInfo();
				tileset->m_sName = valueForKey("name", attributeDict);
				tileset->m_uFirstGid = (unsigned int)atoi(valueForKey("firstgid", attributeDict));
				tileset->m_uSpacing = (unsigned int)atoi(valueForKey("spacing", attributeDict));
				tileset->m_uMargin = (unsigned int)atoi(valueForKey("margin", attributeDict));
				CCSize s;
				s.width = (float)atof(valueForKey("tilewidth", attributeDict));
				s.height = (float)atof(valueForKey("tileheight", attributeDict));
				tileset->m_tTileSize = s;

				pTMXMapInfo->getTilesets()->addObject(tileset);
				tileset->release();
			}
		}
		else if(elementName == "tile")
		{
			CCTMXTilesetInfo* info = pTMXMapInfo->getTilesets()->getLastObject();
			CCStringToStringDictionary *dict = new CCStringToStringDictionary();
			pTMXMapInfo->setParentGID(info->m_uFirstGid + atoi(valueForKey("id", attributeDict)));
			pTMXMapInfo->getTileProperties()->setObject(dict, pTMXMapInfo->getParentGID());
			CC_SAFE_RELEASE(dict);

			pTMXMapInfo->setParentElement(TMXPropertyTile);

		}
		else if(elementName == "layer")
		{
			CCTMXLayerInfo *layer = new CCTMXLayerInfo();
			layer->m_sName = valueForKey("name", attributeDict);

			CCSize s;
			s.width = (float)atof(valueForKey("width", attributeDict));
			s.height = (float)atof(valueForKey("height", attributeDict));
			layer->m_tLayerSize = s;

			std::string visible = valueForKey("visible", attributeDict);
			layer->m_bVisible = !(visible == "0");

			std::string opacity = valueForKey("opacity", attributeDict);
			if( opacity != "" )
			{
				layer->m_cOpacity = (unsigned char)(255 * atof(opacity.c_str()));
			}
			else
			{
				layer->m_cOpacity = 255;
			}

			float x = (float)atof(valueForKey("x", attributeDict));
			float y = (float)atof(valueForKey("y", attributeDict));
			layer->m_tOffset = ccp(x,y);

			pTMXMapInfo->getLayers()->addObject(layer);
			layer->release();

			// The parent element is now "layer"
			pTMXMapInfo->setParentElement(TMXPropertyLayer);

		}
		else if(elementName == "objectgroup")
		{
			CCTMXObjectGroup *objectGroup = new CCTMXObjectGroup();
			objectGroup->setGroupName(valueForKey("name", attributeDict));
			CCPoint positionOffset;
			positionOffset.x = (float)atof(valueForKey("x", attributeDict)) * pTMXMapInfo->getTileSize().width;
			positionOffset.y = (float)atof(valueForKey("y", attributeDict)) * pTMXMapInfo->getTileSize().height;
			objectGroup->setPositionOffset(positionOffset);

			pTMXMapInfo->getObjectGroups()->addObject(objectGroup);
			objectGroup->release();

			// The parent element is now "objectgroup"
			pTMXMapInfo->setParentElement(TMXPropertyObjectGroup);

		}
		else if(elementName == "image")
		{
			CCTMXTilesetInfo *tileset = pTMXMapInfo->getTilesets()->getLastObject();

			// build full path
			std::string imagename = valueForKey("source", attributeDict);
			tileset->m_sSourceImage = CCFileUtils::fullPathFromRelativeFile(imagename.c_str(), pTMXMapInfo->getTMXFileName());

		}
		else if(elementName == "data")
		{
			std::string encoding = valueForKey("encoding", attributeDict);
			std::string compression = valueForKey("compression", attributeDict);

			if( encoding == "base64" )
			{
				int layerAttribs = pTMXMapInfo->getLayerAttribs();
				pTMXMapInfo->setLayerAttribs(layerAttribs | TMXLayerAttribBase64);
				pTMXMapInfo->setStoringCharacters(true);

				if( compression == "gzip" )
				{
					layerAttribs = pTMXMapInfo->getLayerAttribs();
					pTMXMapInfo->setLayerAttribs(layerAttribs | TMXLayerAttribGzip);
				} else
				if (compression == "zlib")
				{
					layerAttribs = pTMXMapInfo->getLayerAttribs();
					pTMXMapInfo->setLayerAttribs(layerAttribs | TMXLayerAttribZlib);
				}
				CCAssert( compression == "" || compression == "gzip" || compression == "zlib", "TMX: unsupported compression method" );
			}
			CCAssert( pTMXMapInfo->getLayerAttribs() != TMXLayerAttribNone, "TMX tile map: Only base64 and/or gzip/zlib maps are supported" );

		}
		else if(elementName == "object")
		{
			char buffer[32];
			CCTMXObjectGroup *objectGroup = pTMXMapInfo->getObjectGroups()->getLastObject();

			// The value for "type" was blank or not a valid class name
			// Create an instance of TMXObjectInfo to store the object and its properties
			CCStringToStringDictionary *dict = new CCStringToStringDictionary();

			// Set the name of the object to the value for "name"
			std::string key = "name";
			CCString *value = new CCString(valueForKey("name", attributeDict));
			dict->setObject(value, key);
			value->release();

			// Assign all the attributes as key/name pairs in the properties dictionary
			key = "type";
			value = new CCString(valueForKey("type", attributeDict));
			dict->setObject(value, key);
			value->release();

			int x = atoi(valueForKey("x", attributeDict)) + (int)objectGroup->getPositionOffset().x;
			key = "x";
			sprintf(buffer, "%d", x);
			value = new CCString(buffer);
			dict->setObject(value, key);
			value->release();

			int y = atoi(valueForKey("y", attributeDict)) + (int)objectGroup->getPositionOffset().y;
			// Correct y position. (Tiled uses Flipped, cocos2d uses Standard)
			y = (int)(pTMXMapInfo->getMapSize().height * pTMXMapInfo->getTileSize().height) - y - atoi(valueForKey("height", attributeDict));
			key = "y";
			sprintf(buffer, "%d", y);
			value = new CCString(buffer);
			dict->setObject(value, key);
			value->release();

			key = "width";
			value = new CCString(valueForKey("width", attributeDict));
			dict->setObject(value, key);
			value->release();

			key = "height";
			value = new CCString(valueForKey("height", attributeDict));
			dict->setObject(value, key);
			value->release();

			// Add the object to the objectGroup
			objectGroup->getObjects()->addObject(dict);
			dict->release();

			// The parent element is now "object"
			pTMXMapInfo->setParentElement(TMXPropertyObject);

		}
		else if(elementName == "property")
		{
			if ( pTMXMapInfo->getParentElement() == TMXPropertyNone )
			{
				CCLOG( "TMX tile map: Parent element is unsupported. Cannot add property named '%s' with value '%s'",
					valueForKey("name", attributeDict), valueForKey("value",attributeDict) );
			}
			else if ( pTMXMapInfo->getParentElement() == TMXPropertyMap )
			{
				// The parent element is the map
				CCString *value = new CCString(valueForKey("value", attributeDict));
				std::string key = valueForKey("name", attributeDict);
				pTMXMapInfo->getProperties()->setObject(value, key);
				value->release();

			}
			else if ( pTMXMapInfo->getParentElement() == TMXPropertyLayer )
			{
				// The parent element is the last layer
				CCTMXLayerInfo *layer = pTMXMapInfo->getLayers()->getLastObject();
				CCString *value = new CCString(valueForKey("value", attributeDict));
				std::string key = valueForKey("name", attributeDict);
				// Add the property to the layer
				layer->getProperties()->setObject(value, key);
				value->release();

			}
			else if ( pTMXMapInfo->getParentElement() == TMXPropertyObjectGroup )
			{
				// The parent element is the last object group
				CCTMXObjectGroup *objectGroup = pTMXMapInfo->getObjectGroups()->getLastObject();
				CCString *value = new CCString(valueForKey("value", attributeDict));
				std::string key = valueForKey("name", attributeDict);
				objectGroup->getProperties()->setObject(value, key);
				value->release();

			}
			else if ( pTMXMapInfo->getParentElement() == TMXPropertyObject )
			{
				// The parent element is the last object
				CCTMXObjectGroup *objectGroup = pTMXMapInfo->getObjectGroups()->getLastObject();
				CCStringToStringDictionary *dict = objectGroup->getObjects()->getLastObject();

				std::string propertyName = valueForKey("name", attributeDict);
				CCString *propertyValue = new CCString(valueForKey("value", attributeDict));
				dict->setObject(propertyValue, propertyName);
				propertyValue->release();
			}
			else if ( pTMXMapInfo->getParentElement() == TMXPropertyTile )
			{
				CCStringToStringDictionary *dict;
				dict = pTMXMapInfo->getTileProperties()->objectForKey(pTMXMapInfo->getParentGID());

				std::string propertyName = valueForKey("name", attributeDict);
				CCString *propertyValue = new CCString(valueForKey("value", attributeDict));
				dict->setObject(propertyValue, propertyName);
				propertyValue->release();
			}
		}
		if (attributeDict)
		{
			attributeDict->clear();
			delete attributeDict;
		}
	}

	void CCTMXMapInfo::endElement(void *ctx, const char *name)
	{
        CC_UNUSED_PARAM(ctx);
		CCTMXMapInfo *pTMXMapInfo = this;
		std::string elementName = (char*)name;

		int len = 0;

		if(elementName == "data" && pTMXMapInfo->getLayerAttribs()&TMXLayerAttribBase64)
		{
			pTMXMapInfo->setStoringCharacters(false);

			CCTMXLayerInfo *layer = pTMXMapInfo->getLayers()->getLastObject();

			std::string currentString = pTMXMapInfo->getCurrentString();
			unsigned char *buffer;
			len = base64Decode((unsigned char*)currentString.c_str(), (unsigned int)currentString.length(), &buffer);
			if( ! buffer )
			{
				CCLOG("cocos2d: TiledMap: decode data error");
				return;
			}

			if( pTMXMapInfo->getLayerAttribs() & (TMXLayerAttribGzip | TMXLayerAttribZlib) )
			{
				unsigned char *deflated;
				CCSize s = layer->m_tLayerSize;
				// int sizeHint = s.width * s.height * sizeof(uint32_t);
				int sizeHint = (int)(s.width * s.height * sizeof(unsigned int));

				int inflatedLen = ZipUtils::ccInflateMemoryWithHint(buffer, len, &deflated, sizeHint);
				CCAssert(inflatedLen == sizeHint, "");

                inflatedLen = (size_t)&inflatedLen; // XXX: to avoid warings in compiler

				delete [] buffer;
				buffer = NULL;

				if( ! deflated )
				{
					CCLOG("cocos2d: TiledMap: inflate data error");
					return;
				}

				layer->m_pTiles = (unsigned int*) deflated;
			}
			else
			{
				layer->m_pTiles = (unsigned int*) buffer;
			}

			pTMXMapInfo->setCurrentString("");

		}
		else if (elementName == "map")
		{
			// The map element has ended
			pTMXMapInfo->setParentElement(TMXPropertyNone);
		}
		else if (elementName == "layer")
		{
			// The layer element has ended
			pTMXMapInfo->setParentElement(TMXPropertyNone);
		}
		else if (elementName == "objectgroup")
		{
			// The objectgroup element has ended
			pTMXMapInfo->setParentElement(TMXPropertyNone);
		}
		else if (elementName == "object")
		{
			// The object element has ended
			pTMXMapInfo->setParentElement(TMXPropertyNone);
		}
	}

	void CCTMXMapInfo::textHandler(void *ctx, const char *ch, int len)
	{
        CC_UNUSED_PARAM(ctx);
		CCTMXMapInfo *pTMXMapInfo = this;
		std::string pText((char*)ch,0,len);

		if (pTMXMapInfo->getStoringCharacters())
		{
			std::string currentString = pTMXMapInfo->getCurrentString();
			currentString += pText;
			pTMXMapInfo->setCurrentString(currentString.c_str());
		}
	}

}//namespace cocos2d


code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
Copyright (c) 2011      Zynga Inc.

http://www.cocos2d-x.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "CCTileMapAtlas.h"
#include "CCFileUtils.h"
#include "CCTextureAtlas.h"
#include "support/image_support/TGAlib.h"
#include "ccConfig.h"

namespace cocos2d {

	// implementation CCTileMapAtlas

	CCTileMapAtlas * CCTileMapAtlas::tileMapAtlasWithTileFile(const char *tile, const char *mapFile, int tileWidth, int tileHeight)
	{
		CCTileMapAtlas *pRet = new CCTileMapAtlas();
		if (pRet->initWithTileFile(tile, mapFile, tileWidth, tileHeight))
		{
			pRet->autorelease();
			return pRet;
		}
		CC_SAFE_DELETE(pRet);
		return NULL;
	}
	bool CCTileMapAtlas::initWithTileFile(const char *tile, const char *mapFile, int tileWidth, int tileHeight)
	{
		this->loadTGAfile(mapFile);
		this->calculateItemsToRender();
		if( CCAtlasNode::initWithTileFile(tile, tileWidth, tileHeight, m_nItemsToRender) )
		{
			m_pPosToAtlasIndex = new StringToIntegerDictionary();
			this->updateAtlasValues();
			this->setContentSize(CCSizeMake((float)(m_pTGAInfo->width*m_uItemWidth),
											(float)(m_pTGAInfo->height*m_uItemHeight)));
			return true;
		}
		return false;
	}
	CCTileMapAtlas::CCTileMapAtlas()
        :m_pTGAInfo(NULL)
		,m_pPosToAtlasIndex(NULL)
		,m_nItemsToRender(0)
	{
	}
	CCTileMapAtlas::~CCTileMapAtlas()
	{
		if (m_pTGAInfo)
		{
			tgaDestroy(m_pTGAInfo);
		}
		if (m_pPosToAtlasIndex)
		{
			m_pPosToAtlasIndex->clear();
			delete m_pPosToAtlasIndex;
			m_pPosToAtlasIndex = NULL;
		}
	}
	void CCTileMapAtlas::releaseMap()
	{
		if (m_pTGAInfo)
		{
			tgaDestroy(m_pTGAInfo);
		}
		m_pTGAInfo = NULL;

		if (m_pPosToAtlasIndex)
		{
			m_pPosToAtlasIndex->clear();
			delete m_pPosToAtlasIndex;
			m_pPosToAtlasIndex = NULL;
		}
	}
	void CCTileMapAtlas::calculateItemsToRender()
	{
		CCAssert( m_pTGAInfo != NULL, "tgaInfo must be non-nil");

		m_nItemsToRender = 0;
		for(int x=0;x < m_pTGAInfo->width; x++ )
		{
			for( int y=0; y < m_pTGAInfo->height; y++ )
			{
				ccColor3B *ptr = (ccColor3B*) m_pTGAInfo->imageData;
				ccColor3B value = ptr[x + y * m_pTGAInfo->width];
				if( value.r )
				{
					++m_nItemsToRender;
				}
			}
		}
	}
	void CCTileMapAtlas::loadTGAfile(const char *file)
	{
		CCAssert( file != NULL, "file must be non-nil");

		//	//Find the path of the file
		//	NSBundle *mainBndl = [CCDirector sharedDirector].loadingBundle;
		//	CCString *resourcePath = [mainBndl resourcePath];
		//	CCString * path = [resourcePath stringByAppendingPathComponent:file];

		m_pTGAInfo = tgaLoad( CCFileUtils::fullPathFromRelativePath(file) );
	#if 1
		if( m_pTGAInfo->status != TGA_OK )
		{
			CCAssert(0, "TileMapAtlasLoadTGA : TileMapAtas cannot load TGA file");
		}
	#endif
	}

	// CCTileMapAtlas - Atlas generation / updates
	void CCTileMapAtlas::setTile(const ccColor3B& tile, const ccGridSize& position)
	{
		CCAssert( m_pTGAInfo != NULL, "tgaInfo must not be nil");
		CCAssert( m_pPosToAtlasIndex != NULL, "posToAtlasIndex must not be nil");
		CCAssert( position.x < m_pTGAInfo->width, "Invalid position.x");
		CCAssert( position.y < m_pTGAInfo->height, "Invalid position.x");
		CCAssert( tile.r != 0, "R component must be non 0");

		ccColor3B *ptr = (ccColor3B*)m_pTGAInfo->imageData;
		ccColor3B value = ptr[position.x + position.y * m_pTGAInfo->width];
		if( value.r == 0 )
		{
			CCLOG("cocos2d: Value.r must be non 0.");
		}
		else
		{
			ptr[position.x + position.y * m_pTGAInfo->width] = tile;

			// XXX: this method consumes a lot of memory
			// XXX: a tree of something like that shall be impolemented
			char buffer[32];
			/*std::string key = itoa(position.x, buffer, 10);*/
			sprintf(buffer, "%d", position.x);
			std::string key = buffer;

			key += ",";
			/*key += itoa(position.y, buffer, 10);*/
			sprintf(buffer, "%d", position.y);
			key += buffer;

			int num = m_pPosToAtlasIndex->find(key)->second;
			this->updateAtlasValueAt(position, tile, num);
		}
	}
	ccColor3B CCTileMapAtlas::tileAt(const ccGridSize& position)
	{
		CCAssert( m_pTGAInfo != NULL, "tgaInfo must not be nil");
		CCAssert( position.x < m_pTGAInfo->width, "Invalid position.x");
		CCAssert( position.y < m_pTGAInfo->height, "Invalid position.y");

		ccColor3B *ptr = (ccColor3B*)m_pTGAInfo->imageData;
		ccColor3B value = ptr[position.x + position.y * m_pTGAInfo->width];

		return value;
	}
	void CCTileMapAtlas::updateAtlasValueAt(const ccGridSize& pos, const ccColor3B& value, unsigned int index)
	{
		ccV3F_C4B_T2F_Quad quad;

		int x = pos.x;
		int y = pos.y;
        float row = (float) (value.r % m_uItemsPerRow);
        float col = (float) (value.r / m_uItemsPerRow);

        float textureWide = (float) (m_pTextureAtlas->getTexture()->getPixelsWide());
        float textureHigh = (float) (m_pTextureAtlas->getTexture()->getPixelsHigh());

#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
        float left		= (2 * row * m_uItemWidth + 1) / (2 * textureWide);
        float right		= left + (m_uItemWidth * 2 - 2) / (2 * textureWide);
        float top		= (2 * col * m_uItemHeight + 1) / (2 * textureHigh);
        float bottom	= top + (m_uItemHeight * 2 - 2) / (2 * textureHigh);
#else
        float left		= (row * m_uItemWidth) / textureWide;
        float right		= left + m_uItemWidth / textureWide;
        float top		= (col * m_uItemHeight) / textureHigh;
        float bottom	= top + m_uItemHeight / textureHigh;
#endif

        quad.tl.texCoords.u = left;
        quad.tl.texCoords.v = top;
        quad.tr.texCoords.u = right;
        quad.tr.texCoords.v = top;
        quad.bl.texCoords.u = left;
        quad.bl.texCoords.v = bottom;
        quad.br.texCoords.u = right;
        quad.br.texCoords.v = bottom;

		quad.bl.vertices.x = (float) (x * m_uItemWidth);
		quad.bl.vertices.y = (float) (y * m_uItemHeight);
		quad.bl.vertices.z = 0.0f;
		quad.br.vertices.x = (float)(x * m_uItemWidth + m_uItemWidth);
		quad.br.vertices.y = (float)(y * m_uItemHeight);
		quad.br.vertices.z = 0.0f;
		quad.tl.vertices.x = (float)(x * m_uItemWidth);
		quad.tl.vertices.y = (float)(y * m_uItemHeight + m_uItemHeight);
		quad.tl.vertices.z = 0.0f;
		quad.tr.vertices.x = (float)(x * m_uItemWidth + m_uItemWidth);
		quad.tr.vertices.y = (float)(y * m_uItemHeight + m_uItemHeight);
		quad.tr.vertices.z = 0.0f;

		m_pTextureAtlas->updateQuad(&quad, index);
	}
	void CCTileMapAtlas::updateAtlasValues()
	{
		CCAssert( m_pTGAInfo != NULL, "tgaInfo must be non-nil");

		int total = 0;

		for(int x=0;x < m_pTGAInfo->width; x++ )
		{
			for( int y=0; y < m_pTGAInfo->height; y++ )
			{
				if( total < m_nItemsToRender )
				{
					ccColor3B *ptr = (ccColor3B*) m_pTGAInfo->imageData;
					ccColor3B value = ptr[x + y * m_pTGAInfo->width];

					if( value.r != 0 )
					{
						this->updateAtlasValueAt(ccg(x,y), value, total);

						char buffer[32];
						/*std::string key = itoa(x, buffer, 10);*/
						sprintf(buffer, "%d", x);
						std::string key = buffer;

						key += ",";
						/*key += itoa(y, buffer, 10);*/
						sprintf(buffer, "%d", y);
						key += buffer;

						m_pPosToAtlasIndex->insert(StringToIntegerPair(key, total));

						total++;
					}
				}
			}
		}
	}
	void CCTileMapAtlas::setTGAInfo(struct sImageTGA* var)
	{
		m_pTGAInfo = var;
	}
	struct sImageTGA * CCTileMapAtlas::getTGAInfo()
	{
		return m_pTGAInfo;
	}

} // namespace cocos2d


code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2009      Valentin Milea

http://www.cocos2d-x.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/

#include "CCTouchDispatcher.h"
#include "CCTouchHandler.h"
#include "CCMutableArray.h"
#include "CCSet.h"
#include "CCTouch.h"
#include "CCTexture2D.h"
#include "support/data_support/ccCArray.h"
#include "ccMacros.h"
#include <algorithm>

/**
 * Used for sort
 */
static bool less(const cocos2d::CCTouchHandler *p1, const cocos2d::CCTouchHandler *p2)
{
	return ((cocos2d::CCTouchHandler*)p1)->getPriority() < ((cocos2d::CCTouchHandler*)p2)->getPriority();
}

namespace   cocos2d {

bool CCTouchDispatcher::isDispatchEvents(void)
{
	return m_bDispatchEvents;
}

void CCTouchDispatcher::setDispatchEvents(bool bDispatchEvents)
{
	m_bDispatchEvents = bDispatchEvents;
}

static CCTouchDispatcher *pSharedDispatcher = NULL;

CCTouchDispatcher* CCTouchDispatcher::sharedDispatcher(void)
{
	// synchronized ??
	if (pSharedDispatcher == NULL)
	{
		pSharedDispatcher = new CCTouchDispatcher();
		pSharedDispatcher->init();
	}

	return pSharedDispatcher;
}

/*
+(id) allocWithZone:(CCZone *)zone
{
	@synchronized(self) {
		CCAssert(sharedDispatcher == nil, @"Attempted to allocate a second instance of a singleton.");
		return [super allocWithZone:zone];
	}
	return nil; // on subsequent allocation attempts return nil
}
*/

bool CCTouchDispatcher::init(void)
{
	m_bDispatchEvents = true;
 	m_pTargetedHandlers = new CCMutableArray<CCTouchHandler*>(8);
 	m_pStandardHandlers = new CCMutableArray<CCTouchHandler*>(4);

 	m_pHandlersToAdd = new CCMutableArray<CCTouchHandler*>(8);
    m_pHandlersToRemove = ccCArrayNew(8);

	m_bToRemove = false;
	m_bToAdd = false;
	m_bToQuit = false;
	m_bLocked = false;

	m_sHandlerHelperData[CCTOUCHBEGAN].m_type = CCTOUCHBEGAN;
	m_sHandlerHelperData[CCTOUCHMOVED].m_type = CCTOUCHMOVED;
	m_sHandlerHelperData[CCTOUCHENDED].m_type = CCTOUCHENDED;
	m_sHandlerHelperData[CCTOUCHCANCELLED].m_type = CCTOUCHCANCELLED;

	return true;
}

CCTouchDispatcher::~CCTouchDispatcher(void)
{
	CC_SAFE_RELEASE(m_pTargetedHandlers);
	CC_SAFE_RELEASE(m_pStandardHandlers);
	CC_SAFE_RELEASE(m_pHandlersToAdd);

	ccCArrayFree(m_pHandlersToRemove);
	m_pHandlersToRemove = NULL;
}

//
// handlers management
//
void CCTouchDispatcher::forceAddHandler(CCTouchHandler *pHandler, CCMutableArray<CCTouchHandler*> *pArray)
{
	unsigned int u = 0;

 	CCMutableArray<CCTouchHandler*>::CCMutableArrayIterator iter;
 	for (iter = pArray->begin(); iter != pArray->end(); ++iter)
 	{
 		CCTouchHandler *h = *iter;
         if (h)
         {
 		    if (h->getPriority() < pHandler->getPriority())
 		    {
 			    ++u;
 		    }

 		    if (h->getDelegate() == pHandler->getDelegate())
 		    {
 			    CCAssert(0, "");
 			    return;
 		    }
         }
 	}

	pArray->insertObjectAtIndex(pHandler, u);
}

void CCTouchDispatcher::addStandardDelegate(CCTouchDelegate *pDelegate, int nPriority)
{
	CCTouchHandler *pHandler = CCStandardTouchHandler::handlerWithDelegate(pDelegate, nPriority);
	if (! m_bLocked)
	{
		forceAddHandler(pHandler, m_pStandardHandlers);
	}
	else
	{
		/* If pHandler is contained in m_pHandlersToRemove, if so remove it from m_pHandlersToRemove and retrun.
		 * Refer issue #752(cocos2d-x)
		 */
		if (ccCArrayContainsValue(m_pHandlersToRemove, pDelegate))
		{
			ccCArrayRemoveValue(m_pHandlersToRemove, pDelegate);
			return;
		}

		m_pHandlersToAdd->addObject(pHandler);
		m_bToAdd = true;
	}
}

void CCTouchDispatcher::addTargetedDelegate(CCTouchDelegate *pDelegate, int nPriority, bool bSwallowsTouches)
{
	CCTouchHandler *pHandler = CCTargetedTouchHandler::handlerWithDelegate(pDelegate, nPriority, bSwallowsTouches);
	if (! m_bLocked)
	{
		forceAddHandler(pHandler, m_pTargetedHandlers);
	}
	else
	{
		/* If pHandler is contained in m_pHandlersToRemove, if so remove it from m_pHandlersToRemove and retrun.
		 * Refer issue #752(cocos2d-x)
		 */
		if (ccCArrayContainsValue(m_pHandlersToRemove, pDelegate))
		{
			ccCArrayRemoveValue(m_pHandlersToRemove, pDelegate);
			return;
		}

		m_pHandlersToAdd->addObject(pHandler);
		m_bToAdd = true;
	}
}

void CCTouchDispatcher::forceRemoveDelegate(CCTouchDelegate *pDelegate)
{
	CCTouchHandler *pHandler;
	CCMutableArray<CCTouchHandler*>::CCMutableArrayIterator  iter;

	// XXX: remove it from both handlers ???

	// remove handler from m_pStandardHandlers
	for (iter = m_pStandardHandlers->begin(); iter != m_pStandardHandlers->end(); ++iter)
	{
		pHandler = *iter;
		if (pHandler && pHandler->getDelegate() == pDelegate)
		{
			m_pStandardHandlers->removeObject(pHandler);
			break;
		}
	}

    // remove handler from m_pTargetedHandlers
	for (iter = m_pTargetedHandlers->begin(); iter != m_pTargetedHandlers->end(); ++iter)
	{
		pHandler = *iter;
		if (pHandler && pHandler->getDelegate() == pDelegate)
		{
			m_pTargetedHandlers->removeObject(pHandler);
			break;
		}
	}
}

void CCTouchDispatcher::removeDelegate(CCTouchDelegate *pDelegate)
{
	if (pDelegate == NULL)
	{
		return;
	}

	if (! m_bLocked)
	{
		forceRemoveDelegate(pDelegate);
	}
	else
	{
		/* If pHandler is contained in m_pHandlersToAdd, if so remove it from m_pHandlersToAdd and retrun.
		 * Refer issue #752(cocos2d-x)
		 */
		CCTouchHandler *pHandler = findHandler(m_pHandlersToAdd, pDelegate);
		if (pHandler)
		{
			m_pHandlersToAdd->removeObject(pHandler);
			return;
		}

		ccCArrayAppendValue(m_pHandlersToRemove, pDelegate);
		m_bToRemove = true;
	}
}

void CCTouchDispatcher::forceRemoveAllDelegates(void)
{
 	m_pStandardHandlers->removeAllObjects();
 	m_pTargetedHandlers->removeAllObjects();
}

void CCTouchDispatcher::removeAllDelegates(void)
{
	if (! m_bLocked)
	{
		forceRemoveAllDelegates();
	}
	else
	{
		m_bToQuit = true;
	}
}

CCTouchHandler* CCTouchDispatcher::findHandler(CCTouchDelegate *pDelegate)
{
	CCMutableArray<CCTouchHandler*>::CCMutableArrayIterator iter;

	for (iter = m_pTargetedHandlers->begin(); iter != m_pTargetedHandlers->end(); ++iter)
	{
		if ((*iter)->getDelegate() == pDelegate)
		{
			return *iter;
		}
	}

	for (iter = m_pStandardHandlers->begin(); iter != m_pStandardHandlers->end(); ++iter)
	{
		if ((*iter)->getDelegate() == pDelegate)
		{
			return *iter;
		}
	}

	return NULL;
}

CCTouchHandler* CCTouchDispatcher::findHandler(CCMutableArray<CCTouchHandler*> *pArray, CCTouchDelegate *pDelegate)
{
	CCAssert(pArray != NULL && pDelegate != NULL, "");

	CCMutableArray<CCTouchHandler*>::CCMutableArrayIterator iter;

	for (iter = pArray->begin(); iter != pArray->end(); ++iter)
	{
		if ((*iter)->getDelegate() == pDelegate)
		{
			return *iter;
		}
	}

	return NULL;
}

void CCTouchDispatcher::rearrangeHandlers(CCMutableArray<CCTouchHandler*> *pArray)
{
	std::sort(pArray->begin(), pArray->end(), less);
}

void CCTouchDispatcher::setPriority(int nPriority, CCTouchDelegate *pDelegate)
{
    CCAssert(pDelegate != NULL, "");

	CCTouchHandler *handler = NULL;

	handler = this->findHandler(pDelegate);

	CCAssert(handler != NULL, "");

	handler->setPriority(nPriority);

	this->rearrangeHandlers(m_pTargetedHandlers);
	this->rearrangeHandlers(m_pStandardHandlers);
}

//
// dispatch events
//
void CCTouchDispatcher::touches(CCSet *pTouches, CCEvent *pEvent, unsigned int uIndex)
{
	CCAssert(uIndex >= 0 && uIndex < 4, "");

	CCSet *pMutableTouches;
	m_bLocked = true;

	// optimization to prevent a mutable copy when it is not necessary
 	unsigned int uTargetedHandlersCount = m_pTargetedHandlers->count();
 	unsigned int uStandardHandlersCount = m_pStandardHandlers->count();
	bool bNeedsMutableSet = (uTargetedHandlersCount && uStandardHandlersCount);

	pMutableTouches = (bNeedsMutableSet ? pTouches->mutableCopy() : pTouches);

	struct ccTouchHandlerHelperData sHelper = m_sHandlerHelperData[uIndex];
	//
	// process the target handlers 1st
	//
	if (uTargetedHandlersCount > 0)
	{
        CCTouch *pTouch;
		CCSetIterator setIter;
		for (setIter = pTouches->begin(); setIter != pTouches->end(); ++setIter)
		{
			pTouch = (CCTouch *)(*setIter);
			CCTargetedTouchHandler *pHandler;
			CCMutableArray<CCTouchHandler*>::CCMutableArrayIterator arrayIter;
			for (arrayIter = m_pTargetedHandlers->begin(); arrayIter != m_pTargetedHandlers->end(); ++arrayIter)
			/*for (unsigned int i = 0; i < m_pTargetedHandlers->num; ++i)*/
			{
                pHandler = (CCTargetedTouchHandler *)(*arrayIter);

                if (! pHandler)
                {
				   break;
                }

				bool bClaimed = false;
				if (uIndex == CCTOUCHBEGAN)
				{
					bClaimed = pHandler->getDelegate()->ccTouchBegan(pTouch, pEvent);

					if (bClaimed)
					{
						pHandler->getClaimedTouches()->addObject(pTouch);
					}
				} else
				if (pHandler->getClaimedTouches()->containsObject(pTouch))
				{
					// moved ended cancelled
					bClaimed = true;

					switch (sHelper.m_type)
					{
					case CCTOUCHMOVED:
						pHandler->getDelegate()->ccTouchMoved(pTouch, pEvent);
						break;
					case CCTOUCHENDED:
						pHandler->getDelegate()->ccTouchEnded(pTouch, pEvent);
						pHandler->getClaimedTouches()->removeObject(pTouch);
						break;
					case CCTOUCHCANCELLED:
						pHandler->getDelegate()->ccTouchCancelled(pTouch, pEvent);
						pHandler->getClaimedTouches()->removeObject(pTouch);
						break;
					}
				}

				if (bClaimed && pHandler->isSwallowsTouches())
				{
					if (bNeedsMutableSet)
					{
						pMutableTouches->removeObject(pTouch);
					}

					break;
				}
			}
		}
	}

	//
	// process standard handlers 2nd
	//
	if (uStandardHandlersCount > 0 && pMutableTouches->count() > 0)
	{
		CCMutableArray<CCTouchHandler*>::CCMutableArrayIterator iter;
		CCStandardTouchHandler *pHandler;
		for (iter = m_pStandardHandlers->begin(); iter != m_pStandardHandlers->end(); ++iter)
		{
			pHandler = (CCStandardTouchHandler*)(*iter);

            if (! pHandler)
            {
			    break;
            }

			switch (sHelper.m_type)
			{
			case CCTOUCHBEGAN:
				pHandler->getDelegate()->ccTouchesBegan(pMutableTouches, pEvent);
				break;
			case CCTOUCHMOVED:
				pHandler->getDelegate()->ccTouchesMoved(pMutableTouches, pEvent);
				break;
			case CCTOUCHENDED:
				pHandler->getDelegate()->ccTouchesEnded(pMutableTouches, pEvent);
				break;
			case CCTOUCHCANCELLED:
				pHandler->getDelegate()->ccTouchesCancelled(pMutableTouches, pEvent);
				break;
			}
		}
	}

	if (bNeedsMutableSet)
	{
		pMutableTouches->release();
	}

	//
	// Optimization. To prevent a [handlers copy] which is expensive
	// the add/removes/quit is done after the iterations
	//
	m_bLocked = false;
	if (m_bToRemove)
	{
		m_bToRemove = false;
		for (unsigned int i = 0; i < m_pHandlersToRemove->num; ++i)
		{
			forceRemoveDelegate((CCTouchDelegate*)m_pHandlersToRemove->arr[i]);
		}
		ccCArrayRemoveAllValues(m_pHandlersToRemove);
	}

	if (m_bToAdd)
	{
		m_bToAdd = false;
 		CCMutableArray<CCTouchHandler*>::CCMutableArrayIterator iter;
         CCTouchHandler *pHandler;
 		for (iter = m_pHandlersToAdd->begin(); iter != m_pHandlersToAdd->end(); ++iter)
 		{
 			pHandler = *iter;
            if (! pHandler)
            {
                break;
            }

		    if (dynamic_cast<CCTargetedTouchHandler*>(pHandler) != NULL)
			{
				forceAddHandler(pHandler, m_pTargetedHandlers);
			}
			else
			{
				forceAddHandler(pHandler, m_pStandardHandlers);
			}
 		}

 		m_pHandlersToAdd->removeAllObjects();
	}

	if (m_bToQuit)
	{
		m_bToQuit = false;
		forceRemoveAllDelegates();
	}
}

void CCTouchDispatcher::touchesBegan(CCSet *touches, CCEvent *pEvent)
{
	if (m_bDispatchEvents)
	{
		this->touches(touches, pEvent, CCTOUCHBEGAN);
	}
}

void CCTouchDispatcher::touchesMoved(CCSet *touches, CCEvent *pEvent)
{
    if (m_bDispatchEvents)
	{
		this->touches(touches, pEvent, CCTOUCHMOVED);
	}
}

void CCTouchDispatcher::touchesEnded(CCSet *touches, CCEvent *pEvent)
{
    if (m_bDispatchEvents)
	{
		this->touches(touches, pEvent, CCTOUCHENDED);
	}
}

void CCTouchDispatcher::touchesCancelled(CCSet *touches, CCEvent *pEvent)
{
    if (m_bDispatchEvents)
	{
		this->touches(touches, pEvent, CCTOUCHCANCELLED);
	}
}
}//namespace   cocos2d


code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2009      Valentin Milea

http://www.cocos2d-x.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/

#include "CCTouchHandler.h"
#include "ccMacros.h"

namespace   cocos2d {

CCTouchDelegate* CCTouchHandler::getDelegate(void)
{
	return m_pDelegate;
}

void CCTouchHandler::setDelegate(CCTouchDelegate *pDelegate)
{
	if (pDelegate)
	{
		dynamic_cast<CCObject*>(pDelegate)->retain();
    }

	dynamic_cast<CCObject*>(pDelegate)->retain();

    if (m_pDelegate)
    {
		dynamic_cast<CCObject*>(m_pDelegate)->release();
    }

	m_pDelegate = pDelegate;
}

int CCTouchHandler::getPriority(void)
{
	return m_nPriority;
}

void CCTouchHandler::setPriority(int nPriority)
{
	m_nPriority = nPriority;
}

int CCTouchHandler::getEnabledSelectors(void)
{
	return m_nEnabledSelectors;
}

void CCTouchHandler::setEnalbedSelectors(int nValue)
{
	m_nEnabledSelectors = nValue;
}

CCTouchHandler* CCTouchHandler::handlerWithDelegate(CCTouchDelegate *pDelegate, int nPriority)
{
	CCTouchHandler *pHandler = new CCTouchHandler();

	if (pHandler)
	{
		if (pHandler->initWithDelegate(pDelegate, nPriority))
		{
			pHandler->autorelease();
		}
		else
		{
			CC_SAFE_RELEASE_NULL(pHandler);
		}
	}

	return pHandler;
}

bool CCTouchHandler::initWithDelegate(CCTouchDelegate *pDelegate, int nPriority)
{
	CCAssert(pDelegate != NULL, "touch delegate should not be null");

	m_pDelegate = pDelegate;

	dynamic_cast<CCObject*>(pDelegate)->retain();

	m_nPriority = nPriority;
	m_nEnabledSelectors = 0;

	return true;
}

CCTouchHandler::~CCTouchHandler(void)
{
	if (m_pDelegate)
	{
		dynamic_cast<CCObject*>(m_pDelegate)->release();
	}
}

// implementation of CCStandardTouchHandler
bool CCStandardTouchHandler::initWithDelegate(CCTouchDelegate *pDelegate, int nPriority)
{
	if (CCTouchHandler::initWithDelegate(pDelegate, nPriority))
	{
		return true;
	}

	return false;
}

CCStandardTouchHandler* CCStandardTouchHandler::handlerWithDelegate(CCTouchDelegate *pDelegate, int nPriority)
{
	CCStandardTouchHandler* pHandler = new CCStandardTouchHandler();

	if (pHandler)
	{
		if (pHandler->initWithDelegate(pDelegate, nPriority))
		{
			pHandler->autorelease();
		}
		else
		{
			CC_SAFE_RELEASE_NULL(pHandler);
		}
	}

	return pHandler;
}

// implementation of CCTargetedTouchHandler

bool CCTargetedTouchHandler::isSwallowsTouches(void)
{
	return m_bSwallowsTouches;
}

void CCTargetedTouchHandler::setSwallowsTouches(bool bSwallowsTouches)
{
	m_bSwallowsTouches = bSwallowsTouches;
}

CCSet* CCTargetedTouchHandler::getClaimedTouches(void)
{
	return m_pClaimedTouches;
}

CCTargetedTouchHandler* CCTargetedTouchHandler::handlerWithDelegate(CCTouchDelegate *pDelegate, int nPriority, bool bSwallow)
{
	CCTargetedTouchHandler *pHandler = new CCTargetedTouchHandler();
	if (pHandler)
	{
		if (pHandler->initWithDelegate(pDelegate, nPriority, bSwallow))
		{
			pHandler->autorelease();
		}
		else
		{
			CC_SAFE_RELEASE_NULL(pHandler);
		}
	}

	return pHandler;
}

bool CCTargetedTouchHandler::initWithDelegate(CCTouchDelegate *pDelegate, int nPriority, bool bSwallow)
{
	if (CCTouchHandler::initWithDelegate(pDelegate, nPriority))
	{
		m_pClaimedTouches = new CCSet();
		m_bSwallowsTouches = bSwallow;

		return true;
	}

	return false;
}

CCTargetedTouchHandler::~CCTargetedTouchHandler(void)
{
	CC_SAFE_RELEASE(m_pClaimedTouches);
}
}//namespace   cocos2d


code:
@echo off
:: This script is used to create an android project.
:: You should modify _ANDROIDTOOLS _CYGBIN _NDKROOT to work under your environment.
:: Don't change it until you know what you do.

setlocal

:: Check if it was run under cocos2d-x root
if not exist "%cd%\create-android-project.bat" echo Error!!! You should run it under cocos2dx root & pause & exit 2

if not exist "%~dpn0.sh" echo Script "%~dpn0.sh" not found & pause & exit 3

:: modify it to work under your environment
set _CYGBIN=d:\programe\cygwin\bin
if not exist "%_CYGBIN%" echo Couldn't find Cygwin at "%_CYGBIN%" & pause & exit 4

:: modify it to work under your environment
set _ANDROIDTOOLS=d:\programe\android\android-sdk\tools
if not exist "%_ANDROIDTOOLS%" echo Couldn't find android sdk tools at "%_ANDROIDTOOLS%" & pause & exit 5

:: modify it to work under your environment
set _NDKROOT=d:\programe\android\ndk\android-ndk-r7b
if not exist "%_NDKROOT%" echo Couldn't find ndk at "%_NDKROOT%" & pause & exit 6

:: create android project
set /P _PACKAGEPATH=Please enter your package path. For example: org.cocos2dx.example:
set /P _PROJECTNAME=Please enter your project name:
if exist "%CD%\%_PROJECTNAME%" echo "%_PROJECTNAME%" exists, please use another name & pause & exit 7
echo "Now cocos2d-x suppurts Android 2.1-update1, 2.2, 2.3 & 3.0"
echo "Other versions have not tested."
call "%_ANDROIDTOOLS%\android.bat" list targets
set /P _TARGETID=Please input target id:
set _PROJECTDIR=%CD%\%_PROJECTNAME%

echo Create android project
call "%_ANDROIDTOOLS%\android.bat" create project -n %_PROJECTNAME% -t %_TARGETID% -k %_PACKAGEPATH% -a %_PROJECTNAME% -p %_PROJECTDIR%

:: Resolve ___.sh to /cygdrive based *nix path and store in %_CYGSCRIPT%
for /f "delims=" %%A in ('%_CYGBIN%\cygpath.exe "%~dpn0.sh"') do set _CYGSCRIPT=%%A

:: Resolve current dir to cygwin path
for /f "delims=" %%A in ('%_CYGBIN%\cygpath.exe "%cd%"') do set _CURRENTDIR=%%A

:: Resolve ndk dir to cygwin path
for /f "delims=" %%A in ('%_CYGBIN%\cygpath.exe "%_NDKROOT%"') do set _NDKROOT=%%A

:: Throw away temporary env vars and invoke script, passing any args that were passed to us
endlocal & %_CYGBIN%\bash --login "%_CYGSCRIPT%" %_CURRENTDIR% %_PROJECTNAME% %_NDKROOT% %_PACKAGEPATH% "windows" -l -b

pause


code:
#!/bin/bash
# This script should be called by create-android-project.bat
# or should be runned in linux shell. It can not be runned under
# cygwin.
# Don't modify the script until you know what you do.

# set environment paramters
NDK_ROOT_LOCAL="/home/laschweinski/android/android-ndk-r5"
ANDROID_SDK_ROOT_LOCAL="/home/laschweinski/android/android-sdk-linux_86"

NEED_BOX2D=false
NEED_CHIPMUNK=false
NEED_LUA=false

# try to get global variable
if [ $NDK_ROOT"aaa" != "aaa" ]; then
    echo "use global definition of NDK_ROOT: $NDK_ROOT"
    NDK_ROOT_LOCAL=$NDK_ROOT
fi

if [ $ANDROID_SDK_ROOT"aaa" != "aaa" ]; then
    echo "use global definition of ANDROID_SDK_ROOT: $ANDROID_SDK_ROOT"
    ANDROID_SDK_ROOT_LOCAL=$ANDROID_SDK_ROOT
fi

# parameters passed to .bat or .sh
PARAMS=

print_usage(){
    echo ERROR!!!
    echo usage
    echo "$0(or corresponding bat file on windows) [-b|--box2d] [-c|--chipmunk] [-l|--lua]"
}

check_param(){
    for param in ${PARAMS[@]}
    do
        case $param in
            -b | --box2d)
                echo using box2d
                NEED_BOX2D=true
                ;;
            -c | --chipmunk)
                echo using chipmunk
                NEED_CHIPMUNK=true
                ;;
            -l | --lua)
                echo using lua
                NEED_LUA=true
                ;;
            -linux)
                // skip it
                ;;
            *)
                print_usage
                exit 1
        esac
    done

    if [ $NEED_BOX2D = "true" ]; then
        if [ $NEED_CHIPMUNK = "true" ]; then
            echo Warning!!!
            echo Use box2d and chipmunk together????
        fi
    fi
}

# check if it was called by .bat file
if [ $# -ge 5 ];then
    if [ $5 = "windows" ];then
        # called by .bat file
        length=`expr $# - 5`
        PARAMS=${@:6:$length}
        check_param
        sh $1/template/android/copy_files.sh $1 $2 $3 $4 $NEED_BOX2D $NEED_CHIPMUNK $NEED_LUA
        exit
    fi
fi

# the bash file should not be called by cygwin
KERNEL_NAME=`uname -s | grep "CYGWIN*"`
if [ $KERNEL_NAME"hi" != "hi" ]; then
    echo "Error!!!"
    echo "Don't run in cygwin. You should run corresponding bat."
    exit
fi

# ok, it was run under linux

# check it was runned in cocos2d-x root
check_path(){
    if [ ! -f create-android-project.sh ];then
        echo Error!!!
        echo Please run in cocos2dx root
        exit
    fi
}

create_android_project(){
    echo "Input package path. For example: org.cocos2dx.example"
    read PACKAGE_PATH
    echo "Now cocos2d-x supports Android 2.1-update1, 2.2, 2.3 & 3.0"
    echo "Other versions have not tested."
    $ANDROID_SDK_ROOT_LOCAL/tools/android list targets
    echo "input target id:"
    read TARGET_ID
    echo "input your project name:"
    read PROJECT_NAME
    PROJECT_DIR=`pwd`/$PROJECT_NAME

    # check if PROJECT_DIR is exist
    if [ -d $PROJECT_DIR ]; then
        echo "$PROJECT_DIR is exist, please use another name"
        exit
    fi

    $ANDROID_SDK_ROOT_LOCAL/tools/android create project -n $PROJECT_NAME -t $TARGET_ID -k $PACKAGE_PATH -a $PROJECT_NAME -p $PROJECT_DIR
}

check_path
PARAMS=$@
check_param
create_android_project

if [ $0 = "linux" ]; then
    # invoked by create-linux-android-project.sh
    sh `pwd`/template/linux/mycopy_files.sh `pwd` $PROJECT_NAME $NDK_ROOT_LOCAL $PACKAGE_PATH $NEED_BOX2D $NEED_CHIPMUNK $NEED_LUA
else
    # invoke template/android/copy_files.sh
    sh `pwd`/template/android/copy_files.sh `pwd` $PROJECT_NAME $NDK_ROOT_LOCAL $PACKAGE_PATH $NEED_BOX2D $NEED_CHIPMUNK $NEED_LUA
fi


code:
set fso = Wscript.CreateObject("Scripting.FileSystemObject")

dim szPrompt, msgRet
szPrompt = "Prompt"

function ReplaceFileContent(fileName, oldStr, newStr)
    set f = fso.opentextfile(fileName)
    s = replace(f.readall, oldStr, newStr)
    f.close
    set r = fso.opentextfile(fileName, 2, true)
    r.write s
end function

function CopyFolder(srcFolder, desFolder)
    if (fso.FolderExists(desFolder)) then
        'msgbox("none:"+srcFolder+":"+desFolder)
        'If the desFolder exist, do nothing.
    else
        CopyFolder = fso.CopyFolder(srcFolder, desFolder)
    end if
end function

function ConfigureProject()
    dim szProjectName
    szProjectName = Inputbox("Please Input Project Name:", szPrompt)

    if szProjectName = "" then
        Wscript.quit
    end if

    if (0 = strcomp(szProjectName, "HelloWorld", 1) or 0 = strcomp(szProjectName, "tests", 1)) then
        msgRet = msgbox("Can not create a project named with "+szProjectName+", Please input again!", 1, szPrompt)
        if (msgRet = 1) then
            call ConfigureProject
        end if
        Wscript.quit
    end if

    if (fso.FolderExists(szProjectName)) then
    else
        fso.CreateFolder(szProjectName)
    end if

    dim badaFolder
    badaFolder = szProjectName + "\bada"
    if (fso.FolderExists(badaFolder)) then
        msgRet = msgbox("The '"+szProjectName+"' project exists, can't override! Please input again!", 1, szPrompt)
        if (msgRet = 1) then
            call ConfigureProject
        end if
        Wcript.quit
    end if

    dim szSrcClass, szSrcBada, szSrcResource
    dim szDesClass, szDesBada, szDesResource

    szSrcClass = "HelloWorld\Classes"
    szSrcBada = "HelloWorld\bada"
    szSrcResource = "HelloWorld\Resources"

    szDesClass = szProjectName+"\Classes"
    szDesBada = szProjectName+"\bada"
    szDesResource = szProjectName+"\Resources"

    call CopyFolder(szSrcClass, szDesClass)
    call CopyFolder(szSrcBada, szDesBada)
    call CopyFolder(szSrcResource, szDesResource)

    dim i
    for i=1 to 2
        call ReplaceFileContent(szProjectName+"\bada\sdk"+cstr(i)+".0\application.xml", "HelloWorld", szProjectName)
        call ReplaceFileContent(szProjectName+"\bada\sdk"+cstr(i)+".0\.project", "HelloWorld", szProjectName)
        call ReplaceFileContent(szProjectName+"\bada\sdk"+cstr(i)+".0\.cproject", "HelloWorld", szProjectName)
    next

    call msgbox("Congratulations, the '"+szProjectName+"' project have been created successfully, please use Bada IDE to import the project!", 0, szPrompt)

end function

call ConfigureProject
Wscript.quit


code:
#!/bin/bash
# This script should be called by create-android-project.bat
# or should be runned in linux shell. It can not be runned under
# cygwin.
# Don't modify the script until you know what you do.

# set environment paramters

bash `pwd`/create-android-project.sh -linux $@


code:
#!/bin/sh

HELLOWORLD_ROOT=`pwd`/HelloWorld

# make directory qnx and copy all files and directories into it
copy_qnx_folder(){
    if [ -d $PROJECT_DIR/qnx ]; then
        echo "The '$PROJECT_NAME' project exists, can't override! Please input again!"
        create_qnx_project
        exit
    fi
    mkdir $PROJECT_DIR/qnx
    echo $HELLOWORLD_ROOT
    for file in `ls -a $HELLOWORLD_ROOT/qnx | grep -E '\.(project|cproject|xml|png|cpp)' `
    do
        file=$HELLOWORLD_ROOT/qnx/$file
        if [ -f $file ];then
            #echo $file
            cp $file $PROJECT_DIR/qnx
        fi
    done
}

copy_cpp_h_from_helloworld(){
    if [ -d $PROJECT_DIR/Classes ]; then
        echo "Classes folder exists, skip copying Classes folder!"
    else
        mkdir $PROJECT_DIR/Classes
        for file in `ls $HELLOWORLD_ROOT/Classes/* | grep -E '.(cpp|h|mk)' `
        do
            if [ -f $file ];then
                #echo $file
                cp $file $PROJECT_DIR/Classes
            fi
        done
    fi
}

# copy resources
copy_resouces(){
    if [ -d $PROJECT_DIR/Resources ]; then
        echo "Resources folder exists, skip copying Resources folder!"
    else
        mkdir $PROJECT_DIR/Resources

        for file in $HELLOWORLD_ROOT/Resources/*
        do
            #echo $file
            cp $file $PROJECT_DIR/Resources
        done
    fi
}

# replace string
modify_file_content(){
    # here should use # instead of /, why??
    sed "s#HelloWorld#$PROJECT_NAME#" $PROJECT_DIR/qnx/$1 > $PROJECT_DIR/qnx/tmp.txt
    rm $PROJECT_DIR/qnx/$1
    mv $PROJECT_DIR/qnx/tmp.txt $PROJECT_DIR/qnx/$1
}

create_qnx_project(){
    echo "Please input your project name:"
    read PROJECT_NAME
    PROJECT_DIR=`pwd`/$PROJECT_NAME

    # check if PROJECT_DIR is exist
    if [ -d $PROJECT_DIR ]; then
        echo ""
    else
        mkdir $PROJECT_DIR
    fi

    copy_qnx_folder
    modify_file_content .project
    modify_file_content .cproject
    modify_file_content bar-descriptor.xml
    copy_cpp_h_from_helloworld
    copy_resouces
    echo "Congratulations, the '$PROJECT_NAME' project have been created successfully, please use QNX IDE to import the project!"
}

create_qnx_project


code:
set fso = Wscript.CreateObject("Scripting.FileSystemObject")

dim szPrompt, msgRet
szPrompt = "Prompt"

function ReplaceFileContent(fileName, oldStr, newStr)
    set f = fso.opentextfile(fileName)
    s = replace(f.readall, oldStr, newStr)
    f.close
    set r = fso.opentextfile(fileName, 2, true)
    r.write s
end function

function CopyFolder(srcFolder, desFolder)
    if (fso.FolderExists(desFolder)) then
        'msgbox("none:"+srcFolder+":"+desFolder)
        'If the desFolder exist, do nothing.
    else
        CopyFolder = fso.CopyFolder(srcFolder, desFolder)
    end if
end function

function ConfigureProject()
    dim szProjectName
    szProjectName = Inputbox("Please Input Project Name:", szPrompt)

    if szProjectName = "" then
        Wscript.quit
    end if

    if (0 = strcomp(szProjectName, "HelloWorld", 1) or 0 = strcomp(szProjectName, "tests", 1)) then
        msgRet = msgbox("Can not create a project named with "+szProjectName+", Please input again!", 1, szPrompt)
        if (msgRet = 1) then
            call ConfigureProject
        end if
        Wscript.quit
    end if

    if (fso.FolderExists(szProjectName)) then
    else
        fso.CreateFolder(szProjectName)
    end if

    dim qnxFolder
    qnxFolder = szProjectName + "\qnx"
    if (fso.FolderExists(qnxFolder)) then
        msgRet = msgbox("The '"+szProjectName+"' project exists, can't override! Please input again!", 1, szPrompt)
        if (msgRet = 1) then
            call ConfigureProject
        end if
        Wcript.quit
    end if

    dim szSrcClass, szSrcQnx, szSrcResource
    dim szDesClass, szDesQnx, szDesResource

    szSrcClass = "HelloWorld\Classes"
    szSrcQnx = "HelloWorld\qnx"
    szSrcResource = "HelloWorld\Resources"

    szDesClass = szProjectName+"\Classes"
    szDesQnx = szProjectName+"\qnx"
    szDesResource = szProjectName+"\Resources"

    call CopyFolder(szSrcClass, szDesClass)
    call CopyFolder(szSrcQnx, szDesQnx)
    call CopyFolder(szSrcResource, szDesResource)

    call ReplaceFileContent(szProjectName+"\qnx\bar-descriptor.xml", "HelloWorld", szProjectName)
    call ReplaceFileContent(szProjectName+"\qnx\.project", "HelloWorld", szProjectName)
    call ReplaceFileContent(szProjectName+"\qnx\.cproject", "HelloWorld", szProjectName)

    call msgbox("Congratulations, the '"+szProjectName+"' project have been created successfully, please use QNX IDE to import the project!", 0, szPrompt)

end function

call ConfigureProject
Wscript.quit


code:
/*!
@mainpage cocos2d-x

@image html cocos2dx_portrait.png

@section sec1 About cocos2d-x
cocos2d-x open source project is designed to be a cross-platform 2D game engine for building 2D games, demos and other graphical/interactive mobile applications.
It runs on OpenGL ES 1.1, and is written in C++ language, provides C++ API.\n
This project is based on the famous "cocos2d-iphone" project, and will keep pace with it. \n

- website:                          http://www.cocos2d-x.org/
- forum:                            http://forum.cocos2d-x.org/
- twitter:                          http://twitter.com/cocos2dx/
- weibo:                            http://weibo.com/cocos2dx/
- wiki:                             http://wiki.cocos2d-x.org/
- show cases:                       http://www.cocos2d-x.org/projects/cocos2d-x/apps

- Tutorials of Cocos2dxSimpleGame
- Installation and First run
- DEVELOP FAQ

\n

@section sec2 License
Copyright (c) 2010-2012 cocos2d-x.org \n
\n
Permission is hereby granted, free of charge, to any person obtaining a copy \n
of this software and associated documentation files (the "Software"), to deal \n
in the Software without restriction, including without limitation the rights \n
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell \n
copies of the Software, and to permit persons to whom the Software is \n
furnished to do so, subject to the following conditions: \n
\n
The above copyright notice and this permission notice shall be included in \n
all copies or substantial portions of the Software. \n
\n
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \n
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \n
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \n
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN \n
THE SOFTWARE. \n
\n

@section sec3 Get the source code
- Stable version: \n
    - publish at http://download.cocos2d-x.org/
- Last code: \n
    - http://github.com/cocos2d/cocos2d-x/

@section sec4 How to contribute
- Fork our repository on github, commit your changes, and send a "pull request" to us. We will merge your contribution to master
- Any suggestion, bug fix, improvment will be appreciated.

*/