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

【cocos2dx开发技巧9】自定义控件-定制字体工具

2013-08-13 17:32 357 查看
转发,请保持地址:/article/7718256.html
在Cocos2dx中已经有三种字体工具了,几本上能够满足游戏中对字体的要求。其中CCLabelTTF使用系统的ttf文件,CCLabelBMFont字体工具制作,CCLabelAtlas使用贴图,不过字体的大小要相同等约束。CCLabelTTF最为方便,速度最慢,效果最少;CCLabelBMFont方便性速度效果等都居中,CCLabelAtlas不太方便,不过性能和效果最优,可以使用美工制作的字体。我在这里要使用美工提供的字体,所以好像只能够用CCLabelAtlas了,不过感觉还是不很方便,所以自己定义了一个字体工具,分享给大家。实现方式和CCLabelBMFont、CCLabelAtlas相似。不过可以把字体图片打包到spreetSheet中,然后提供一个映射就可以了,使用方式如下:

const char* map[] = {
"0", "0.png",
"1", "1.png",
"2", "2.png",
"3", "3.png",
"4", "4.png",
"5", "5.png",
"6", "6.png",
"7", "7.png",
"8", "8.png",
"9", "9.png",
",", ",.png",
":", "colon.png",
"/", "dghh.png",
".", "dot.png",
};
//http://stackoverflow.com/questions/2236197/c-easiest-way-to-initialize-an-stl-vector-with-hardcoded-elements
std::vector<const char*> mm(map, map+sizeof(map)/sizeof(map[0])); // parameter: fist, last
// 注意这里少了加载plist的步骤,这个和CCSpriteBatchNode的用法是一样的,因为MyLabel就是其子类,我以后再加上
MyLabel* mylabel = MyLabel::create("font.png", 10, mm, .9f);  //font.png是通过texturePacker之类工具生成的文件
mylabel->setString("12.231");


下面是实现(其中MyRGBAProtocolAdapter请参考上一片文章):

class MyLabel : public CCSpriteBatchNode , public CCLabelProtocol, public MyRGBAProtocolAdapter {
private:
std::map<char, CCSprite*> words;
std::vector<ccV3F_C4B_T2F_Quad> quads;
float mlWidth, mlHeight, scale;
const char* label;

public:

static MyLabel* create(const char* fileImage, unsigned int capacity, std::vector<const char*>& map, float scale /*字体间距*/) {
MyLabel* pRet = new MyLabel();
if (pRet && pRet->doMyInit(fileImage, capacity, map, scale)) {
pRet->autorelease();
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}

// save the words to map, in order to access them quickly
bool doMyInit(const char* fileImage, unsigned int capacity, std::vector<const char*>& map, float _scale = 1.f /*字体间距*/)  {
this->scale = _scale;
int size = map.size();
if (!initWithFile(fileImage, capacity) || size%2!=0) {
return false;
}
size /= 2;
for (int i=0; i<size; i++) {
char key = map[2*i][0];
const char* fn = map[2*i+1];
CCSprite* sprite = CCSprite::createWithSpriteFrameName(fn);
if (!sprite) {
CCLog("[MyLabel] The sprite with name '%s' is not exists!", fn);
return false;
}
words[key] = sprite;  // insert the sprites
sprite->retain();  // keep sprite from deleting
}
return true;
}

virtual ~MyLabel() { // delete the sprite
for (std::map<char, CCSprite*>::iterator it = words.begin(); it!=words.end(); it++) {
CC_SAFE_DELETE(it->second);
}
}

const char* getString() {
return label;
}

void setString(const char* _label) {
this->label = _label;
_setString(label);
}

void _setString(std::string str) {
// clean and make enough room for new str
m_pobTextureAtlas->removeAllQuads();
quads.resize(str.length());
int index = 0;
mlWidth = 0;
mlHeight = 0;

if (str.length() > m_pobTextureAtlas->getCapacity()) {
increaseAtlasCapacity();
}

for (std::string::iterator it = str.begin(); it!=str.end(); it++, index++) {
CCSprite * sprite = NULL;

// make sure the character is in the map
std::map<char, CCSprite*>::iterator wit = words.find(*it);
if (wit==words.end()) {
CCLog("The character '%c' is not found in the map, please check!", *it);
return;
} else {
sprite = wit->second;
}

// calculate the position of the sprite;
CCSize size = sprite->getContentSize();
sprite->setPosition(ccp(mlWidth + size.width/2*scale, 0));
mlWidth += size.width * scale;
mlHeight = size.height > mlHeight ? size.height : mlHeight;

// insert the quote, the sprite->updateTransform() will do the following job
sprite->setBatchNode(this);
sprite->setAtlasIndex(index);
sprite->setDirty(true);
sprite->updateTransform();

quads[index] = sprite->getQuad();
}
// correct the size of batch
setContentSize(ccp(mlWidth, mlHeight));
}

protected:
// ========= MyRGBAProtocolAdapter begin ============
CCArray* getRGBAChildren() {
return getChildren();
}

CCNode* getRGBAParent() {
return getParent();
}

void updateDisplayedColor(const ccColor3B& parentColor) {
_displayedColor.r = _realColor.r * parentColor.r/255.0;
_displayedColor.g = _realColor.g * parentColor.g/255.0;
_displayedColor.b = _realColor.b * parentColor.b/255.0;

_updateMLColor();
}

virtual void updateDisplayedOpacity(GLubyte parentOpacity) {
_displayedOpacity = _realOpacity * parentOpacity/255.0;

_updateMLColor();
}

void _updateMLColor() {
ccColor4B color4 = {
_displayedColor.r * _displayedOpacity/255.0f,
_displayedColor.g * _displayedOpacity/255.0f,
_displayedColor.b * _displayedOpacity/255.0f,
_displayedOpacity };
int idx = 0;
for (std::vector<ccV3F_C4B_T2F_Quad>::iterator it = quads.begin(); it!=quads.end(); it++, idx++) {
it->bl.colors = color4;
it->br.colors = color4;
it->tl.colors = color4;
it->tr.colors = color4;
m_pobTextureAtlas->updateQuad(&(*it), idx);
}
}

// ========= MyRGBAProtocolAdapter end ============

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: