转发,请保持地址: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特性添加到自定义类中了。