• cocos2d-x 模态对话框的实现


    心情不好,恩,不扯淡了,直接讲。


    ==================================

    在泰然看了一篇实现模态对话框的文章,写的还不错,然后在其基础上加了我简单加了一层灰色透明背景,这样子界面效果看起来会更友好一点,好吧,原谅我的无耻,原创转载什么的也不在意了,原文在这里,今天感觉有点累,恩,主要是大神不能带我飞了,很是失落,好吧,不说废话了。

    在游戏中,我们常常需要实现弹出一个模态对话框,比如说游戏暂停,退出提示对话框等

    对话框特点如下:


    1.可定制的,比如说背景图,标题,文本,按钮等,根据需要添加和设置

    2.需要屏蔽对话框下层的触摸

    3.为了友好的效果显示,把不可触摸的部分变为灰色


    先来看一张效果图:




    为了完成这样一个效果,思路如下:


    1.设计一个弹出对话框的类PopupLayer,继承于LayerColor,这样子我们就可以设置背景版透明,看起来好像把对话框下层的变灰暗了


            setColor(ccc3(0,0,0));  
            setOpacity(128);  


    2.添加触摸事件,屏蔽下层触摸,也就是在Layer中设置不向下传递

            //add layer touch event
    	auto listener = EventListenerTouchOneByOne::create();
    	listener->setSwallowTouches(true);//不向下传递触摸
    	listener->onTouchBegan = CC_CALLBACK_2(PopupLayer::onTouchBegan, this);
    	listener->onTouchMoved = CC_CALLBACK_2(PopupLayer::onTouchMoved, this);
    	listener->onTouchEnded = CC_CALLBACK_2(PopupLayer::onTouchEnded, this);
    	auto dispatcher = Director::getInstance()->getEventDispatcher();
    	dispatcher->addEventListenerWithSceneGraphPriority(listener, this);

    3.PopupLayer类 实现 可定制对话框标题,按钮,文本,背景图片等


        //标题
        void setTitle(const char* title, int fontsize = 20);
        //文本
        void setContentText(const char* text, int fontsize = 20, int padding = 50, int paddintTop = 100);
        //设置button回调事件
        void setCallbackFunc(Ref* target, SEL_CallFuncN callfun);
         //添加button
        bool addButton(const char* normalImage, const char* selectedImage, const char* title, int tag = 0);

    4.按钮回调函数实现也比较简单,首先设置外部的回调对象和回调函数


        Ref* m_callbackListener;    //回调对象
        SEL_CallFuncN m_callback;   //回调函数
    
        //设置按钮的回调函数
        void PopupLayer::setCallbackFunc(Ref* target, SEL_CallFuncN callfun){
        m_callbackListener = target;
        m_callback = callfun;  
        }


    然后在PopupLayer类中比如说我们添加一个菜单按钮


     // 创建图片菜单按钮
        auto item = MenuItemImage::create(
            normalImage,
            selectedImage,
            CC_CALLBACK_1(PopupLayer::buttonCallBack,this));
        item->setTag(tag);

    设置button回调函数,然后由这个回调函数去调用外部的button监听函数,然后关闭对话框


    //button回调函数
        void PopupLayer::buttonCallBack(Ref* pSender){
        Node* node = dynamic_cast<Node*>(pSender);
        CCLog("【====PopupLayer::buttonCallBack====】touch tag: %d", node->getTag());
        if (m_callback && m_callbackListener){
            (m_callbackListener->*m_callback)(node);
        }
        this->removeFromParent();}


    5.然后用法也比较简单,如果需要对话框内容显示中文,可以参考:cocos2d-x 3.0 使用Sax解析xml文档(解决中文显示问题)这篇文章

        //弹出对话框
        pl = PopupLayer::create("BackGround.png",Size(400,350));
        pl->setTitle("title");
        pl->setContentText("Are you sure exit?", 20, 60, 250);
        pl->setCallbackFunc(this, callfuncN_selector(WelcomeScene::popButtonCallback));//设置按钮回调
        pl->addButton("pop_button.png", "pop_button.png", "yes", 0);
        pl->addButton("pop_button.png", "pop_button.png", "no", 1);
        this->addChild(pl);

    外部回调函数实现,根据tag判断点了什么按钮


    void WelcomeScene::popButtonCallback(Node *pNode){
        CCLog("【=====WelcomeScene::popButtonCallback======】button call back. tag: %d", pNode->getTag());
        //exit
        if(pNode->getTag() == 0){
            Director::getInstance()->end();
        }
    }



    恩,思路大概这样子,完整的对话框类如下,亲们可以复制直接使用

    #pragma once
    
    #include "cocos2d.h"
    #include "cocos-ext.h"
    
    using namespace cocos2d;
    using namespace cocos2d::extension;
    
    class PopupLayer : public LayerColor{
    public:
    	PopupLayer();
    	~PopupLayer();
    	
    	virtual bool init();
    	CREATE_FUNC(PopupLayer);
    	static PopupLayer* create(const char* backgroundImage,Size dialogSize);
    
    	//touch事件监听 屏蔽向下触摸
    	bool onTouchBegan(Touch *touch, Event *event);
    	void onTouchMoved(Touch *touch, Event *event);
    	void onTouchEnded(Touch* touch, Event* event);
    
    	//标题
    	void setTitle(const char* title, int fontsize = 20);
    	//文本
    	void setContentText(const char* text, int fontsize = 20, int padding = 50, int paddintTop = 100);
    	//设置button回调事件
    	void setCallbackFunc(Ref* target, SEL_CallFuncN callfun);
    	//添加button
    	bool addButton(const char* normalImage, const char* selectedImage, const char* title, int tag = 0);
    
    	virtual void onEnter();
    	virtual void onExit();
    
    	void backgroundFinish();
    
    private:
    	
    	void buttonCallBack(Ref* pSender);
    
    	// 文字内容两边的空白区
    	int m_contentPadding;
    	int m_contentPaddingTop;
    
    	Size m_dialogContentSize;
    
    	Ref* m_callbackListener;
    	SEL_CallFuncN m_callback;
    
    	//set and get
    	CC_SYNTHESIZE_RETAIN(Menu*, m__pMenu, MenuButton);
    	CC_SYNTHESIZE_RETAIN(Sprite*, m__sfBackGround, SpriteBackGround);
    	CC_SYNTHESIZE_RETAIN(Scale9Sprite*, m__s9BackGround, Sprite9BackGround);
    	CC_SYNTHESIZE_RETAIN(LabelTTF*, m__ltTitle, LabelTitle);
    	CC_SYNTHESIZE_RETAIN(LabelTTF*, m__ltContentText, LabelContentText);
    };

    cpp文件实现如下:


    #include "PopupLayer.h"
    
    PopupLayer::PopupLayer():
    	m__pMenu(NULL)
    	, m_contentPadding(0)
    	, m_contentPaddingTop(0)
    	, m_callbackListener(NULL)
    	, m_callback(NULL)
    	, m__sfBackGround(NULL)
    	, m__s9BackGround(NULL)
    	, m__ltContentText(NULL)
    	, m__ltTitle(NULL)
    {
    
    }
    
    PopupLayer::~PopupLayer(){
    	CC_SAFE_RELEASE(m__pMenu);
    	CC_SAFE_RELEASE(m__sfBackGround);
    	CC_SAFE_RELEASE(m__ltContentText);
    	CC_SAFE_RELEASE(m__ltTitle);
    	CC_SAFE_RELEASE(m__s9BackGround);
    }
    
    bool PopupLayer::init(){
    	if(!LayerColor::init()){
    		return false;
    	}
    	// 初始化需要的 Menu
    	Menu* menu = Menu::create();
    	menu->setPosition(CCPointZero);
    	setMenuButton(menu);
    
    	//add layer touch event
    	auto listener = EventListenerTouchOneByOne::create();
    	listener->setSwallowTouches(true);
    	listener->onTouchBegan = CC_CALLBACK_2(PopupLayer::onTouchBegan, this);
    	listener->onTouchMoved = CC_CALLBACK_2(PopupLayer::onTouchMoved, this);
    	listener->onTouchEnded = CC_CALLBACK_2(PopupLayer::onTouchEnded, this);
    	auto dispatcher = Director::getInstance()->getEventDispatcher();
    	dispatcher->addEventListenerWithSceneGraphPriority(listener, this);
    
    	setColor(ccc3(0,0,0));  
    	setOpacity(128);  
    
    	return true;
    }
    
    bool PopupLayer::onTouchBegan(Touch *touch, Event *event){
    	return true;
    }
    
    void PopupLayer::onTouchMoved(Touch *touch, Event *event){
    
    }
    
    void PopupLayer::onTouchEnded(Touch* touch, Event* event){
    
    }
    
    PopupLayer* PopupLayer::create(const char* backgroundImage, Size dialogSize){
    	
    	PopupLayer* layer = PopupLayer::create();
    	
    //	layer->setSpriteBackGround(Sprite::create(backgroundImage));
    	layer->setSprite9BackGround(Scale9Sprite::create(backgroundImage));
    
    	layer->m_dialogContentSize = dialogSize;
    
    	return layer;
    }
    
    void PopupLayer::setTitle(const char* title, int fontsize /* = 20 */){
    	LabelTTF* label = LabelTTF::create(title,"",fontsize);
    	setLabelTitle(label);
    }
    
    void PopupLayer::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 PopupLayer::setCallbackFunc(Ref* target, SEL_CallFuncN callfun){
    	m_callbackListener = target;
    	m_callback = callfun;    
    }
    
    bool PopupLayer::addButton(const char* normalImage, const char* selectedImage, const char* title, int tag /* = 0 */){
    	
    	auto size = Director::getInstance()->getWinSize();
    	auto center = Point(size.width / 2, size.height / 2);
    
    	// 创建图片菜单按钮
    	auto item = MenuItemImage::create(
    		normalImage,
    		selectedImage,
    		CC_CALLBACK_1(PopupLayer::buttonCallBack,this));
    	item->setTag(tag);
    	item->setPosition(center);
    
    	// 添加文字说明并设置位置
    	Size itemSize = item->getContentSize();
    	LabelTTF* ttf = LabelTTF::create(title, "", 20);
    	ttf->setColor(Color3B(0, 0, 0));
    	ttf->setPosition(Point(itemSize.width / 2, itemSize.height / 2));
    	item->addChild(ttf);
    
    	getMenuButton()->addChild(item);
    
    	return true;
    }
    
    void PopupLayer::buttonCallBack(Ref* pSender){
    	Node* node = dynamic_cast<Node*>(pSender);
    	CCLog("【====PopupLayer::buttonCallBack====】touch tag: %d", node->getTag());
    	if (m_callback && m_callbackListener){
    		(m_callbackListener->*m_callback)(node);
    	}
    	this->removeFromParent();
    }
    
    void PopupLayer::onEnter(){
    	LayerColor::onEnter();
    
    	Size winSize = CCDirector::getInstance()->getWinSize();
    	Point pCenter = Point(winSize.width / 2, winSize.height / 2);
    
    //	Size contentSize ;
    	// 设定好参数,在运行时加载
    	//如果没有设置 ContentSize ,那么采取的方案是,窗口大小与传入图片一样大
    // 	if (getContentSize().equals(this->getParent()->getContentSize())) {
    // 		getSpriteBackGround()->setPosition(ccp(winSize.width / 2, winSize.height / 2));
    // 		this->addChild(getSpriteBackGround(), 0, 0);
    // 		contentSize = getSpriteBackGround()->getTexture()->getContentSize();
    // 	} else {
    // 		Scale9Sprite *background = getSprite9BackGround();
    // 		background->setContentSize(getContentSize());
    // 		background->setPosition(ccp(winSize.width / 2, winSize.height / 2));
    // 		this->addChild(background, 0, 0);
    // 		contentSize = getContentSize();
    // 	}
    	//添加背景图片
    	Scale9Sprite *background = getSprite9BackGround();
    	background->setContentSize(m_dialogContentSize);
    	background->setPosition(Point(winSize.width / 2, winSize.height / 2));
    	this->addChild(background,0,0);
    
    	// 弹出效果
    	Action* popupLayer = Sequence::create(
    		ScaleTo::create(0.0, 0.0),
    		ScaleTo::create(0.2, 1.05),
    		ScaleTo::create(0.2, 0.95),
    		ScaleTo::create(0.1, 1.0), 
    		CallFunc::create(CC_CALLBACK_0(PopupLayer::backgroundFinish,this)),
    		NULL
    		);
    	background->runAction(popupLayer);
    
    
    
    }
    
    void PopupLayer::backgroundFinish(){
    
    	Size winSize = CCDirector::getInstance()->getWinSize();
    	Point pCenter = Point(winSize.width / 2, winSize.height / 2);
    
    	// 添加按钮,并设置其位置
    	this->addChild(getMenuButton());
    	float btnWidth = m_dialogContentSize.width / (getMenuButton()->getChildrenCount() + 1);
    
    	Vector<Node*> vector = getMenuButton()->getChildren();
    	Ref* pObj = NULL;
    	int i = 0;
    	for(Node* pObj : vector){
    		Node* node = dynamic_cast<Node*>(pObj);
    		node->setPosition(Point( winSize.width / 2 - m_dialogContentSize.width / 2 + btnWidth * (i + 1), winSize.height / 2 - m_dialogContentSize.height / 3));
    		i++;
    	}
    
    	// 显示对话框标题
    	if (getLabelTitle()){
    		getLabelTitle()->setPosition(ccpAdd(pCenter, ccp(0, m_dialogContentSize.height / 2 - 35.0f)));
    		this->addChild(getLabelTitle());
    	}
    
    	// 显示文本内容
    	if (getLabelContentText()){
    		CCLabelTTF* ltf = getLabelContentText();
    		ltf->setPosition(ccp(winSize.width / 2, winSize.height / 2));
    		ltf->setDimensions(CCSizeMake(m_dialogContentSize.width - m_contentPadding * 2, m_dialogContentSize.height - m_contentPaddingTop));
    		ltf->setHorizontalAlignment(kCCTextAlignmentLeft);
    		this->addChild(ltf);
    	}
    }
    
    
    
    void PopupLayer::onExit(){
    
    	CCLog("popup on exit.");
    	CCLayerColor::onExit();
    }
    


  • 相关阅读:
    ThinkPHP 3.2.2 视图模板中使用字符串截取函数
    Java实现洛谷 P2802 回家
    Java实现洛谷 P2802 回家
    Java实现 蓝桥杯VIP 算法提高 change
    Java实现 蓝桥杯VIP 算法提高 change
    Java实现 蓝桥杯VIP 算法提高 change
    Java实现蓝桥杯G将军
    Java实现蓝桥杯G将军
    Java实现蓝桥杯G将军
    Java实现 蓝桥杯 算法提高 字符串压缩
  • 原文地址:https://www.cnblogs.com/fzll/p/3954597.html
Copyright © 2020-2023  润新知