转:cocos2d-x里的TiledMap出现黑线和抖动的解决方案(不影响其他类使用)

本文转载自 cocos2d-x里的TiledMap出现黑线和抖动的解决方案(不影响其他类使用)

 

今天搞tiled map发现黑边,开始认为是反锯齿问题,但发现无论开启与否都有边,只是程度不同而已。简单网上搜了下发现有解决方案是 修改ccconfig.h让

#define CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL 1
同时开启tile图块texture的反锯齿避免抖动。
 
但简单看了下CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL, 发现对texture coordinates作了圈限制。
这是原始的注释:
If enabled, the texture coordinates will be calculated by using this formula:
- texCoord.left = (rect.origin.x*2+1) / (texture.wide*2);
- texCoord.right = texCoord.left + (rect.size.width*2-2)/(texture.wide*2);
 
The same for bottom and top.
 
This formula prevents artifacts by using 99% of the texture.
The "correct" way to prevent artifacts is by using the spritesheet-artifact-fixer.py or a similar tool.
 
Affected nodes:
- CCSprite / CCSpriteBatchNode and subclasses: CCLabelBMFont, CCTMXTiledMap
- CCLabelAtlas
- CCQuadParticleSystem
- CCTileMap
 
可见影响了全部CCSprite,事实也发现Sprite只要使用的贴图是紧贴边的,周围都有可能都被切掉了一部分。
其实你只要解决tilemap的显示问题,就没必要去动到别的类。简单看了下加载tiledmap相关源码,其实只需很小改动。
 
首先不要改CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL, 让它仍然是0.
知道的是tiledmap显示部分要用到CCSprite,但这个CCSprite要CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL开启时的作用, 所以这里要新建个CCSprite的子类CCSpriteTileMap。
 
class CCSpriteTileMap : public CCSprite 
{
protected:
virtual void setTextureCoords(CCRect rect);
};
 
void CCSpriteTileMap::setTextureCoords( CCRect rect )
{
rect = CC_RECT_POINTS_TO_PIXELS(rect);
 
CCTexture2D *tex = m_pobBatchNode ? m_pobTextureAtlas->getTexture() : m_pobTexture;
if (! tex)
{
return;
}
 
float atlasWidth = (float)tex->getPixelsWide();
float atlasHeight = (float)tex->getPixelsHigh();
 
float left, right, top, bottom;
 
if (m_bRectRotated)
{
#if 1//CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
left    = (2*rect.origin.x+1)/(2*atlasWidth);
right    = left+(rect.size.height*2-2)/(2*atlasWidth);
top        = (2*rect.origin.y+1)/(2*atlasHeight);
bottom    = top+(rect.size.width*2-2)/(2*atlasHeight);
#else
left    = rect.origin.x/atlasWidth;
right    = (rect.origin.x+rect.size.height) / atlasWidth;
top        = rect.origin.y/atlasHeight;
bottom    = (rect.origin.y+rect.size.width) / atlasHeight;
#endif // CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
 
if (m_bFlipX)
{
CC_SWAP(top, bottom, float);
}
 
if (m_bFlipY)
{
CC_SWAP(left, right, float);
}
 
m_sQuad.bl.texCoords.u = left;
m_sQuad.bl.texCoords.v = top;
m_sQuad.br.texCoords.u = left;
m_sQuad.br.texCoords.v = bottom;
m_sQuad.tl.texCoords.u = right;
m_sQuad.tl.texCoords.v = top;
m_sQuad.tr.texCoords.u = right;
m_sQuad.tr.texCoords.v = bottom;
}
else
{
#if 1//CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
left    = (2*rect.origin.x+1)/(2*atlasWidth);
right    = left + (rect.size.width*2-2)/(2*atlasWidth);
top        = (2*rect.origin.y+1)/(2*atlasHeight);
bottom    = top + (rect.size.height*2-2)/(2*atlasHeight);
#else
left    = rect.origin.x/atlasWidth;
right    = (rect.origin.x + rect.size.width) / atlasWidth;
top        = rect.origin.y/atlasHeight;
bottom    = (rect.origin.y + rect.size.height) / atlasHeight;
#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
 
if(m_bFlipX)
{
CC_SWAP(left,right,float);
}
 
if(m_bFlipY)
{
CC_SWAP(top,bottom,float);
}
 
m_sQuad.bl.texCoords.u = left;
m_sQuad.bl.texCoords.v = bottom;
m_sQuad.br.texCoords.u = right;
m_sQuad.br.texCoords.v = bottom;
m_sQuad.tl.texCoords.u = left;
m_sQuad.tl.texCoords.v = top;
m_sQuad.tr.texCoords.u = right;
m_sQuad.tr.texCoords.v = top;
}
}
 
CCTileMapAtlas.cpp里
CCTileMapAtlas::updateAtlasValueAt 函数中将CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL强行开启
#if 1//CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
    float left        = (2 * row * itemWidthInPixels + 1) / (2 * textureWide);
    float right       = left + (itemWidthInPixels * 2 - 2) / (2 * textureWide);
    float top         = (2 * col * itemHeightInPixels + 1) / (2 * textureHigh);
    float bottom      = top + (itemHeightInPixels * 2 - 2) / (2 * textureHigh);
#else
    float left        = (row * itemWidthInPixels) / textureWide;
    float right       = left + itemWidthInPixels / textureWide;
    float top         = (col * itemHeightInPixels) / textureHigh;
    float bottom      = top + itemHeightInPixels / textureHigh;
#endif
 
 
然后找到CCTMXLayer类里面申请new CCSprite的地方替换成new CCSpriteTileMap就OK了。
发现有两处,在这两个函数内
CCTMXLayer::reusedTileWithRect
CCTMXLayer::tileAt
 
完工!重新BUILD,就看不见恶心的黑线了,同时也不影响别的类使用。
 
想想如果cocos2d出CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL这个定义最初目的是为了解决tiledmap显示问题的话,为什么不独立出一个针对tiledmap显示问题的编译项呢?当然还有其他目的就另当别论了。
 
注明下笔者用的cocos2d-x版本是2.1.5,其实2.0.0后版本应该都适用
posted @ 2015-03-31 11:21  -浮云骑士-  阅读(415)  评论(0编辑  收藏  举报