您的位置:首页 > 移动开发 > Cocos引擎

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

2014-02-28 08:42 597 查看
文章转载地址:http://blog.sina.com.cn/s/blog_4508e4860101dzkj.html

今天搞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后版本应该都适用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: