转发,请保持地址:http://blog.csdn.net/stalendp/article/details/9951187
在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");
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 ============ };