在游戏开发中,为了获得更好的交互效果,经常使用对话框,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);
};
#endifC++实现部分:#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版权协议,转载请附上原文出处链接和本声明。