在使用CCTMXLayer添加移除tile时发现的问题

使用CCTMXLayer做了一个小测试,需要经常添加或移除tile,添加时使用方法setTileGID,移除时使用方法removeTileAt。为了使tile在出现时有些效果,使用tileAt方法获取sprite。
问题: tileAt发生各种奇怪的问题,如本该移除的tile没有移除,在移除(0,0)的tile时报错等。不使用tileAt获取sprite则一切正常。
检查发现CCTMXLayer继承自CCSpriteBatchNode,sprite只有在tileAt时才会创建,在删除tile时是如果sprite存在使用这行代码:
CCSpriteBatchNode::removeChild(sprite, true);
继续跟踪找到这个函数void CCSpriteBatchNode::removeSpriteFromAtlas(CCSprite *pobSprite);
其中如下这段代码:
// update all sprites beyond this one
unsigned int count = m_pobDescendants->count();

		for(; uIndex < count; ++uIndex)
		{
			CCSprite* s = (CCSprite*)(m_pobDescendants->objectAtIndex(uIndex));
			s->setAtlasIndex( s->getAtlasIndex() - 1 );
		}

觉得有问题,它的逻辑是将m_pobDescendants中排在待删除对象后面的sprite的atlasIndex减1;而实际的需求应当是将m_pobDescendants中所有atlasIndex大于或等于待删除对象的atlasIndex减1;把整个函数修改一下:

void CCSpriteBatchNode::removeSpriteFromAtlas(CCSprite *pobSprite)
{
	unsigned int popSpriteAtlasIndex=pobSprite->getAtlasIndex();
	
	// remove from TextureAtlas
	m_pobTextureAtlas->removeQuadAtIndex(pobSprite->getAtlasIndex());

	// Cleanup sprite. It might be reused (issue #569)
	pobSprite->useSelfRender();

	unsigned int uIndex = m_pobDescendants->indexOfObject(pobSprite);
	if (uIndex != UINT_MAX)
	{
		m_pobDescendants->removeObjectAtIndex(uIndex);

		// update all sprites beyond this one
		
		unsigned int count = m_pobDescendants->count();
		//{sayid
		for(int i=0; i < count; i++)
		{
			CCSprite* s = (CCSprite*)(m_pobDescendants->objectAtIndex(i));
			if( s->getAtlasIndex()>=popSpriteAtlasIndex)
				s->setAtlasIndex( s->getAtlasIndex() - 1 );
		}
		//}
	}

	// remove children recursively
	CCArray *pChildren = pobSprite->getChildren();
	if (pChildren && pChildren->count() > 0)
	{
        CCObject* pObject = NULL;
        CCARRAY_FOREACH(pChildren, pObject)
        {
            CCSprite* pChild = (CCSprite*) pObject;
            if (pChild)
            {
                removeSpriteFromAtlas(pChild);
            }
        }
	}
}

发现一切症状消除,其它相关的逻辑没仔细看,也不知道这样改有风险没。。。。

CCSpriteBatchNode * CCSpriteBatchNode::addSpriteWithoutQuad(CCSprite*child, unsigned int z, int aTag)
{
    CCAssert( child != NULL, "Argument must be non-nil");
    /// @todo CCAssert( ], @"CCSpriteSheet only supports CCSprites as children");

    // quad index is Z
    child->setAtlasIndex(z);

    // XXX: optimize with a binary search
    int i=0;
    if (m_pobDescendants && m_pobDescendants->count() > 0)
    {
        CCObject* pObject = NULL;
        CCARRAY_FOREACH(m_pobDescendants, pObject)
        {
            CCSprite* pChild = (CCSprite*) pObject;
			if (pChild && (pChild->getAtlasIndex() <= z))	// >=改为<=即可
            {
                ++i;
            }
        }
    }
    m_pobDescendants->insertObject(child, i);

    // IMPORTANT: Call super, and not self. Avoid adding it to the texture atlas array
    CCNode::addChild(child, z, aTag);
    return this;
}
CCSpriteBatchNode * CCSpriteBatchNode::addSpriteWithoutQuad(CCSprite*child, unsigned int z, int aTag)
{
    CCAssert( child != NULL, "Argument must be non-nil");
    /// @todo CCAssert( ], @"CCSpriteSheet only supports CCSprites as children");

    // quad index is Z
    child->setAtlasIndex(z);

    // XXX: optimize with a binary search
    int i=0;
    if (m_pobDescendants && m_pobDescendants->count() > 0)
    {
        CCObject* pObject = NULL;
        CCARRAY_FOREACH(m_pobDescendants, pObject)
        {
            CCSprite* pChild = (CCSprite*) pObject;
			if (pChild && (pChild->getAtlasIndex() <= z))	// >=改为<=即可
            {
                ++i;
            }
        }
    }
    m_pobDescendants->insertObject(child, i);

    // IMPORTANT: Call super, and not self. Avoid adding it to the texture atlas array
    CCNode::addChild(child, z, aTag);
    return this;
}