【cocos2dx开发技巧8】自定义控件-使自定义控件具有RGBA特性

转发,请保持地址:http://blog.csdn.net/stalendp/article/details/9948545

虽然CCNodeRGBA,CCLayerRGBA,sprite等提供颜色和透明度的设置,但有时候要自定义控件,要自己去实现那些功能。比如,我要扩充一个CCSpriteBatchNode,同时要要具有颜色和透明度的设置,这个时候就需要自己动手了。

其实为自己的控件添加RGBA特性并不是很难,只要继承CCRGBAProtocol,然后把CCNodeRGBA的实现方案贴到新加的类中就可以了。不过这样不便于代码的重用,所以我在改造代码的过程中使用了“适配器设计模式”。 这也是这片文章要介绍的一点。

贴上我的设配器类:MyRGBAProtocolAdapter

class MyRGBAProtocolAdapter: public CCRGBAProtocol {
protected:
	GLubyte		_displayedOpacity, _realOpacity;
	ccColor3B	_displayedColor, _realColor;
	bool		_cascadeOpacityEnabled, _cascadeColorEnabled;
protected:
	virtual CCArray* getRGBAChildren() = 0;
	virtual CCNode* getRGBAParent() = 0;
	
public:
	MyRGBAProtocolAdapter() :
	_cascadeColorEnabled(true),
	_cascadeOpacityEnabled(true),
	_displayedOpacity(255),
	_realOpacity(255),
	_displayedColor(ccc3(255, 255, 255)),
	_realColor(ccc3(255, 255, 255)) {
		
	}
	
	virtual void setColor(const ccColor3B& color) {
		_displayedColor = _realColor = color;
		
		if (_cascadeColorEnabled)
		{
			ccColor3B parentColor = ccWHITE;
			CCRGBAProtocol *parent = dynamic_cast<CCRGBAProtocol*>(getRGBAParent());
			if (parent && parent->isCascadeColorEnabled())
			{
				parentColor = parent->getDisplayedColor();
			}
			
			updateDisplayedColor(parentColor);
		}
	}
	
    virtual const ccColor3B& getColor(void) {
		return _realColor;
	}
	
    virtual const ccColor3B& getDisplayedColor(void) {
		return _displayedColor;
	}
	
    virtual GLubyte getDisplayedOpacity(void) {
		return _displayedOpacity;
	}
	
    virtual GLubyte getOpacity(void) {
		return _realOpacity;
	}
    
    virtual void setOpacity(GLubyte opacity) {
		_displayedOpacity = _realOpacity = opacity;
		
		if (_cascadeOpacityEnabled)
		{
			GLubyte parentOpacity = 255;
			CCRGBAProtocol* pParent = dynamic_cast<CCRGBAProtocol*>(getRGBAParent());
			if (pParent && pParent->isCascadeOpacityEnabled())
			{
				parentOpacity = pParent->getDisplayedOpacity();
			}
			this->updateDisplayedOpacity(parentOpacity);
		}
	}
	
    virtual void setOpacityModifyRGB(bool bValue) {
	}
	
    virtual bool isOpacityModifyRGB(void) {
		return false;
	}
	
    virtual bool isCascadeColorEnabled(void) {
		return _cascadeColorEnabled;
	}
	
    virtual void setCascadeColorEnabled(bool cascadeColorEnabled) {
		_cascadeColorEnabled = cascadeColorEnabled;
	}
    
    virtual 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;
		
		if (_cascadeColorEnabled)
		{
			CCObject *obj = NULL;
			CCARRAY_FOREACH(getRGBAChildren(), obj)
			{
				CCRGBAProtocol *item = dynamic_cast<CCRGBAProtocol*>(obj);
				if (item)
				{
					item->updateDisplayedColor(_displayedColor);
				}
			}
		}
	}
    
    virtual bool isCascadeOpacityEnabled(void) {
		return _cascadeOpacityEnabled;
	}
	
    virtual void setCascadeOpacityEnabled(bool cascadeOpacityEnabled) {
		_cascadeOpacityEnabled = cascadeOpacityEnabled;
	}
	
    virtual void updateDisplayedOpacity(GLubyte parentOpacity) {
		_displayedOpacity = _realOpacity * parentOpacity/255.0;
		
		if (_cascadeOpacityEnabled)
		{
			CCObject* pObj;
			CCARRAY_FOREACH(getRGBAChildren(), pObj)
			{
				CCRGBAProtocol* item = dynamic_cast<CCRGBAProtocol*>(pObj);
				if (item)
				{
					item->updateDisplayedOpacity(_displayedOpacity);
				}
			}
		}
	}
};


注意到,其实MyRGBAProtocolAdapter类是一个抽象类,下面的两个方法是要被子类实现的:

	virtual CCArray* getRGBAChildren() = 0;
	virtual CCNode* getRGBAParent() = 0;


虽然多继承不好,不过我这里还是使用了,下面是我的实现类:

/**
 可以改变颜色和透明度的 Sprite batch Node
 **/

#define BBB_AIM_DU 0.3
 
class BBBatch : public CCSpriteBatchNode, public MyRGBAProtocolAdapter { // 1)继承MyRGBAProtocolAdapter
public:
	static BBBatch* create(const char* fileImage, unsigned int capacity) {
		BBBatch *batchNode = new BBBatch();
		if (batchNode && batchNode->initWithFile(fileImage, capacity)) {
			batchNode->autorelease();
			return batchNode;
		}
		CC_SAFE_DELETE(batchNode);
		return NULL;
	}
	
	void dark() {
		runAction(CCTintTo::create(BBB_AIM_DU, 150, 150, 150));
		runAction(CCFadeTo::create(BBB_AIM_DU, 255*0.6));
	}
	
	void normal() {
		runAction(CCTintTo::create(BBB_AIM_DU, 255, 255, 255));
		runAction(CCFadeTo::create(BBB_AIM_DU, 255));
	}
	//2)下面将实现两个抽象类
	// ========= MyRGBAProtocolAdapter begin ============ 
	CCArray* getRGBAChildren() {
		return getChildren();
	}
	CCNode* getRGBAParent() {
		return getParent();
	}
	// ========= MyRGBAProtocolAdapter end ============
};

这样就可以简单方便地把RGBA特性添加到自定义类中了。

原文地址:https://www.cnblogs.com/keanuyaoo/p/3255895.html