cocos2d基础学习--自定义对话框实现

       在游戏开发中,为了获得更好的交互效果,经常使用对话框,cocos实现对话框也比较容易,说到底对话框也是一个Layer。我们在添加Layer之前首先对对话框进行一定的设置,之后在Layer的OnEnter方法中对界面进行一个动态的加载,另外我们需要重写OnTouchBegin方法,以屏蔽其他的触摸事件。下面是我实现的一个简单对话框

                                                  

创建C++类DialogLayer实现对话框界面,头文件如下

#ifndef _DialogLayer_
#define _DialogLayer_

#include "cocos2d.h"
USING_NS_CC;

class DialogLayer :public Layer
{
public:
	DialogLayer();
	~DialogLayer();
	virtual bool init();
	CREATE_FUNC(DialogLayer);

	//virtual void registerWithTouchDispatcher(void);
	bool onTouchBegan(Touch *touch, Event *unused_event);

	static DialogLayer * create(const char* backgroundImage);
	void setTitle(const char* title ,int fontsize=20);
	void setContentText(const char* text ,int fontsize=20 ,int padding=50 ,int paddintTop=100);
	void setCallbackFunc(CCObject* target, SEL_CallFuncN callfun);
	
	bool addButton(const char* normalImage, const char* selectedImage, const char* title, int tag=0);
	virtual void onEnter();

private:
	void buttonCallback(CCObject* pSender);

    // 文字内容两边的空白区
    int m_contentPadding;
    int m_contentPaddingTop;
    
    CCObject* m_callbackListener;
    SEL_CallFuncN m_callback;

	//利用cocos中的宏来添加get与set方法,最后的参数表示方法名中get与set之后相接的部分
    CC_SYNTHESIZE_RETAIN(Menu*, m_pMenu, MenuButton);
    CC_SYNTHESIZE_RETAIN(Sprite*, m_sfBackGround, SpriteBackGround);
    CC_SYNTHESIZE_RETAIN(LabelTTF*, m_ltTitle, LabelTitle);
    CC_SYNTHESIZE_RETAIN(LabelTTF*, m_ltContentText, LabelContentText);

};


#endif
C++实现部分:
#include "DialogLayer.h"
USING_NS_CC;

DialogLayer::DialogLayer():
m_pMenu(NULL)
, m_contentPadding(0)
, m_contentPaddingTop(0)
, m_callbackListener(NULL)
, m_callback(NULL)
, m_sfBackGround(NULL)
, m_ltContentText(NULL)
, m_ltTitle(NULL)
{
    
}

DialogLayer::~DialogLayer(){
    CC_SAFE_RELEASE(m_pMenu);
    CC_SAFE_RELEASE(m_sfBackGround);
    CC_SAFE_RELEASE(m_ltContentText);
    CC_SAFE_RELEASE(m_ltTitle);
}

bool DialogLayer::init(){
	if(!Layer::init()){
		return false;
	}
	this->setContentSize(Size::ZERO);
    // 初始化需要的 Menu
	Menu* menu = Menu::create();
    menu->setPosition(0, 0);
	setMenuButton(menu);
        
	setTouchEnabled(true);

	return true;
}

//屏蔽向下的监听事件
bool DialogLayer::onTouchBegan(Touch *pTouch, Event *pEvent){
    return true;
}

DialogLayer* DialogLayer::create(const char *backgroundImage){
    DialogLayer* ml = DialogLayer::create();
    ml->setSpriteBackGround(Sprite::create(backgroundImage));
    return ml;
}

//设置标题
void DialogLayer::setTitle(const char *title, int fontsize){
    LabelTTF* ltfTitle = LabelTTF::create(title, "", fontsize);
    setLabelTitle(ltfTitle);
}

//设置对话框要显示的内容
void DialogLayer::setContentText(const char *text, int fontsize, int padding, int paddingTop){
    LabelTTF* ltf = LabelTTF::create(text, "", fontsize);
    setLabelContentText(ltf);
    m_contentPadding = padding;
    m_contentPaddingTop = paddingTop;
}

//设置回调接口
void DialogLayer::setCallbackFunc(cocos2d::CCObject *target, SEL_CallFuncN callfun){
    m_callbackListener = target;
    m_callback = callfun;    
}


bool DialogLayer::addButton(const char *normalImage, const char *selectedImage, const char *title, int tag){
	Size winSize = Director::getInstance()->getVisibleSize();
    Point pCenter(winSize.width / 2, winSize.height / 2);
    
    // 创建图片菜单按钮
	MenuItemImage* menuImage = MenuItemImage::create(normalImage, selectedImage, this, menu_selector(DialogLayer::buttonCallback));
    menuImage->setTag(tag);
    menuImage->setPosition(pCenter);
    
    // 添加文字说明并设置位置
    Size imenu = menuImage->getContentSize();
    LabelTTF* ttf = LabelTTF::create(title, "", 20);
	ttf->setColor(Color3B::BLACK);
    ttf->setPosition(imenu.width / 2, imenu.height / 2);
    menuImage->addChild(ttf, 1);
    
    getMenuButton()->addChild(menuImage, 1);
    return true;
}

void DialogLayer::buttonCallback(cocos2d::CCObject *pSender){
    Node* node = dynamic_cast<Node*>(pSender);
	//当回调接口不为空时,执行回调接口
    if (m_callback && m_callbackListener){
        (m_callbackListener->*m_callback)(node);
    }
    this->removeFromParent();
}

void DialogLayer::onEnter(){
    Layer::onEnter();
 
	Size winSize = Director::getInstance()->getVisibleSize();
    
    Size contentSize;
    // 设定好参数,在运行时加载
    getSpriteBackGround()->setPosition(winSize.width / 2, winSize.height / 2);
	this->addChild(getSpriteBackGround(), 0, 0);
	contentSize = getSpriteBackGround()->getTexture()->getContentSize();
    // 添加按钮,并设置其位置
    this->addChild(getMenuButton());
    float btnWidth = contentSize.width / (getMenuButton()->getChildrenCount() + 1);
    
	Vector<Node*> vecArray = getMenuButton()->getChildren();
    CCObject* pObj = NULL;
    int i = 0;
	for(auto& e : vecArray){
		Node* node = dynamic_cast<Node*>(e);
		node->setPosition(Point(winSize.width/2 - contentSize.width/2+btnWidth*(i+1),winSize.height - contentSize.height-20));
		i++;
	}
    
    // 显示对话框标题
    if (getLabelTitle()){
		getLabelTitle()->setPosition(winSize.width/2, winSize.height/2 + (contentSize.height / 2 - 35.0f));
        this->addChild(getLabelTitle());
    }
    
    // 显示文本内容
    if (getLabelContentText()){
        LabelTTF* ltf = getLabelContentText();
        ltf->setPosition(winSize.width / 2, winSize.height / 2);
        ltf->setDimensions(CCSizeMake(contentSize.width - m_contentPadding * 2, contentSize.height - m_contentPaddingTop));
        ltf->setHorizontalAlignment(TextHAlignment::LEFT);//设置对齐方式
        this->addChild(ltf);
    }

    // 弹出效果,我们可以实现自己的动画效果
    Action* popupLayer = Sequence::create(ScaleTo::create(0.0, 0.0),
					      ScaleTo::create(0.06, 1.05),
                                              ScaleTo::create(0.08, 0.95),
                                              ScaleTo::create(0.08, 1.0), NULL);
    this->runAction(popupLayer);

}
接下来在HelloWorld层中加入该对话框,我们在回调接口中保存了一个Tag,可以根据这个Tag来判断点击的是哪一个按钮
void HelloWorld::menuCloseCallback(Ref* pSender)
{
	showDialog();
}

void HelloWorld::showDialog(){
	// 定义一个弹出层,传入一张背景图
	DialogLayer* pl = DialogLayer::create("BackGround.png");
    pl->setTitle("MyDialog_Title");
    pl->setContentText("This is my dialog_contenttext with a pop", 20, 60, 250);
    // 设置回调函数,回调传回一个 CCNode 以获取 tag 判断点击的按钮
    // 这只是作为一种封装实现,如果使用 delegate 那就能够更灵活的控制参数了
    pl->setCallbackFunc(this, callfuncN_selector(HelloWorld::buttonCallback));
    // 添加按钮,设置图片,文字,tag 信息
    pl->addButton("btn_n.png", "btn_p.png", "Yes", 0);
    pl->addButton("btn_n.png", "btn_p.png", "No", 1);
    // 添加到当前层
    this->addChild(pl, 1);
}

void HelloWorld::buttonCallback(cocos2d::Node *pNode){
	//根据tag来判断点击的时哪个按钮
    log("button call back. tag: %d", pNode->getTag());
}





版权声明:本文为smbroe原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。