cocos2dx 3.3 Label对指定字符设置颜色

Label可以通过getLetter(i)获取位于字符串i位置的字符(不支持system类型创建的label,我这边是用TTF),然后通过setColor设置字符的颜色。但是有时候i不确定,所以我在这边自己做了一些处理。比如“获得了紫色品质的装备”,想让“紫色品质”四个字变成紫色,可以这样做:“获得了#2C%s#2C的装备。然后再用String::createWithFormat()一下,就得到字符串——“获得了#2C紫色品质#2C的装备”,这里#2C代表紫色。这个可以自己设定。然后在对字符串进行处理。主要是找出并保存#2C的位置,并删除#2C。然后根据找出来的#2C的位置,进行getLetter(i),再setColor()。部分代码如下:

vector<int> posVec;
vector<int> colorVec;
posVec.clear();
int position=0;
int lastPos = 0;
int lastTraversalPos = 0;
while((position = strContent.find("#",position))!=string::npos)
{
int cPosition = strContent.find("C",position);
if (cPosition != string::npos && (cPosition - position) > 1 && strContent[cPosition] == 'C')
{// 如果%后面找不到C或者%C中间没有数字则不进来
int color = 0;
for (int m = 1; m < (cPosition - position); m ++)
{
auto charColor = strContent.substr(position + m,1);
color += atoi(charColor.c_str()) + (cPosition - position - m - 1) * 10;
}
if (position != lastPos)
{
int strNum = 0;
int m = lastTraversalPos;
for (; m < position; )
{
char c = strContent[m];
if (c >= 0 && c <= 127)
{
strNum ++;
m += 1;
}
else if (c >= 192 && c <= 223)
{
strNum ++;
m += 2;
}
else if (c >= 224 && c <= 239)
{
strNum ++;
m += 3;
}
else if (c >= 240 && c <= 247)
{
strNum ++;
m += 4;
}
else
{
strNum ++;
m += 3;
}
}
position = strNum + lastPos;
lastPos = position;
lastTraversalPos = m;
}
posVec.push_back(position);
colorVec.push_back(color);
//position=s.find_first_of(flag,position);
strContent.erase(lastTraversalPos,3);
}
else
{
position ++;
}
}

这里会有一个问题,就是如果你设置了文本的宽度,即setDimensions(),并且字符串的长度超过宽度的时候,会自动换行,那么Label原来的字符串就会被插入相对应个数的’n',这样你在getLetter的时候有可能获取到的不是你想要的字符。这时候就要跟到引擎代码里面去看。发现在getLetter的时候会内部会调用Label::updateContent()函数。这个函数里面会调用alignText(),这将会对字符串进行重新排版,有需要换行的话,会自动在相应位置插入'\n'。所以我们可以记录下插入'\n'的位置。跟着源代码进去发现在CCLabelTextFormatter.cpp里面的multilineText()函数进行插入'\n'处理的。所以可以在这里面添加一个函数,获取记录下的位置。然后对我们之前保存的#2C的位置进行调整。插入的位置如果小于#2C的位置,那么#2C就要+1了。部分代码如下:

m_pLabel->setString(strContent.c_str());
m_pLabel->updateContent();

vector<int> insertCharacterPosVec = m_pLabel->getInsertCharacterPos();
for (int originalItr = 0; originalItr < posVec.size(); originalItr ++)
{// 如果字符串的长度超过了文本框的宽度,会自动换行,这时候会在原来的string上插入'\n',整个string长度发生改变。导致接下来的getLetter找不到想要的。所以在这里做处理。
for (int vecItr = 0; vecItr < insertCharacterPosVec.size(); vecItr ++)
{
if (posVec[originalItr] > insertCharacterPosVec[vecItr])
{
posVec[originalItr] ++;
}
}
}


还会有一个问题就是如果同一个Label进行多次的setString的时候可能会出现”Assertion failed: (index>=0 && index<_totalQuads),function removeQuadAtIndex”这个错误。我在setString之前调用一下label->removeAllChildrenWithCleanup(true)就好了。

写得比较乱,主要说明一下大概思路,也算是笔记吧~~

相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...