cocos2d-x 模态对话框的实现

摘要:
也就是说,在层中,设置为不向下传递//addlayertouch ventautolister=EventListenerTouchOneByOne::create();listener-˃setSwallowTouches;//不要传递触摸监听器-˃onTouchBegan=CC_CALLBACK_2;listener-˃onTouchMoved=CC_ CALLBACK_2;listener-˃onTouchEnded=CC_CALLBACK_2;autodispatcher=控制器::getInstance()-˃getEventDispatcher();dispatcher-˃addEventListenerWithSceneGraphPriority;3.PopupLayer类实现了自定义的对话框标题、按钮、文本、背景图像等//title voisetTitle//text voisetContentText//设置按钮回调事件voisetCallbackFunc//Add buttonbooladdButton;4.按钮回调函数的实现也相对简单。首先,设置外部回调对象和回调函数Ref*m_callbackListener;//回调对象SEL_ CallFuncNm_回调;//回调函数//设置按钮voidPopupLayer::setCallbackFunc{m_callbackListener=target;m_Callback=callgun;}的回调函数,然后在PopupLayer类中添加菜单按钮,例如,//创建图像菜单按钮autoitem=MenuItemImage:Create;item-˃setTag;设置按钮回调函数。如果需要以中文显示对话框,可以参考文章:cocos2d-x3.0使用Sax//A对话框pl=PopupLayer::create pop-up解析xml文档;pl-˃setTitle;pl-˃setContentText(“是否退出?

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


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

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

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

对话框特点例如以下:


1.可定制的,比方说背景图,标题,文本,按钮等,依据须要加入和设置

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

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


先来看一张效果图:


cocos2d-x 模态对话框的实现第1张


为了完毕这样一个效果,思路例如以下:


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();
}


免责声明:文章转载自《cocos2d-x 模态对话框的实现》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇[AWS] AWS查看k8s中etcd数据下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

cocos2d实例移动精灵

原文链接:http://iphonedev.net/2009/05/10/cocos2d-example-move-sprite/ (注:原文写的较早,与现在的版本有点出入,这里我直接换成目前版本) Cocos2d 引擎大大的简化了iphone游戏开发的过程。在这个实例中,我们将用一个红色的小方块图片做为精灵,当我们触摸屏幕时,精灵将会平滑的移动到触摸处,...

Cocos2d-x之物理世界(创建静态的物体)

Cocos2d-x之物理世界(创建静态的物体) 在HelloWorldScene.h中添加如下内容 //创建一个地板 void addGround(); HelloWorldScene。cpp 1 #include "HelloWorldScene.h" 2 #include "cocostudio/CocoStudio.h" 3 #include "ui...

cocos2d-x关于CCTableView的“乱序问题”的理解

Cocos2d-x有一个不错的控件CCTableView。之前用的时候发现有cell的顺序错乱和重复出现的问题。后来仔细看了一下源码,发现是自己用法错误。但是网上有人说是一个bug,要改源码。我发现2.04以上的源码都是没问题的。 先来看看网上说的改源码是怎么样改的: CCTableViewCell*CCTableView::dequeueCell() {...

cocos2d-x学习 之一

最近准备学习cocos2d-x的开发,首先要搭建一下开发环境。今天就先搭建一下开发环境。本人系统为Mint-15 64位的linux,以下的开发环境只用于linux。首先到cocos2d-x的官网上下载安装包,由于cocos2d-x是开源的,所以我们可以查看源码,从以下地址下载: http://www.cocos2d-x.org/download 我们下载2...

Cocos2d-x 3.0 触摸机制

在Cocos2dx 3.0版本中,废弃了以往2.x版本的写法,我们先来看一下Layer.h中的一段代码: 1 2 3 4 5 6 7 8 9 10 11 //单点触摸 virtualboolonTouchBegan(Touch*touch,Event*unused_event); virtualvoidonTouchMo...

‎Cocos2d-x 学习笔记(15.1) EventDispatcher

EventDispatcher对监听器进行管理,围绕着监听器工作。可以添加、删除、暂停/恢复监听器、分发事件到监听器。 1. 一些成员 /** 把ListenerID和同ID监听器的容器对应 */ std::unordered_map<EventListener::ListenerID, EventListenerVector*>...