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

转发,请保持地址: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");

下面是实现(其中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 ============
	
};


你可能感兴趣的:(C++,字体,cocos2dx,控件)