在《【Cocos2dx】使用CCControlButton创建按钮、按钮点击事件,点击事件中的组件获取,setPosition的坐标问题》(点击打开链接)已经介绍过Cocos2dx的按钮,怎么用CCScale9Sprite与CCControlButton实现,然而这样的按钮必须要有文字与图片配合起来才能够实现,有时我们只需要一个文字按钮,或者纯图片按钮。
同时,虽然在《【Cocos2dx】利用导演类、场景类完成重新开始游戏、暂停游戏、关闭游戏功能》(点击打开链接)中已经介绍过Cocos2dx的暂停功能怎么实现,但是这样的暂停画面,一片黑白,就放一个按钮实在是难看,一般别人的暂停画面都是拥有当前游戏画面的淡化背景。
下面,就用一个小例子说明这个问题:
如上图,在HelloWorld场景,放上一个官方自带的Helloworld.png,设置一个Pause文字按钮在主页上不停上下运动,点击这个Pause文字按钮就会来到PauseScene这个暂停画面,PauseScene的背景构成就是当前Helloworld的游戏状态。
这个Cocos2dx的文件结构图如下:
首先是HelloWorldScene.h,一些简单的声明:
#include "cocos2d.h" #include "PauseScene.h"//暂停要切到这个场景,因此必须有这句 USING_NS_CC;//一旦在头文件声明用到了CC,就必须有这句 class HelloWorld : public cocos2d::CCLayer { public: virtual bool init(); static cocos2d::CCScene* scene(); CREATE_FUNC(HelloWorld); private: void pause(CCObject* pSender);//暂停的按钮事件 };
之后是HelloWorldScene.cpp,这里包含三个部分。
对于纯文字按钮,是要先创建文字,再根据此文字创建菜单项,再将菜单项添加菜单,最后再把菜单放到问题。此菜单仅一个菜单项,等于就是一个文字按钮。暂时没找到更好的,创建纯文字,不带图片的按钮的方法
纯图片按钮,则比较简单,可以与纯文字按钮的创建一样,无须为此图片先创建经历,直接对菜单项指明按下、不按下的两张图片即可。
此处对比与CCScale9Sprite与CCControlButton,组合文字、图片的按钮创建。
(2)不间断的重复动作序列
不间断的重复动作序列是创建两个分动作之后,先用CCSequence将它们组合起来,再利用CCRepeatForever将其转化为一个CCFiniteTimeAction动作,给组件运行。
关于动作序列在《【Cocos2dx】基本动作、动作序列与动作合并》(点击打开链接)已经说过了,这里只是进一步深化而已。
(3)关于用当前游戏状态作为暂停背景
在当前的场景,先要用CCRenderTexture遍历当前的场景,创建纹理。
#include "HelloWorldScene.h" CCScene* HelloWorld::scene()//场景的创建,Cocos2dx要求层必须放在场景中 { CCScene *scene = CCScene::create(); HelloWorld *layer = HelloWorld::create(); scene->addChild(layer); return scene; } bool HelloWorld::init()//层的初始化函数。 { CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();//获取当前层的尺寸 //创建一个背景精灵 CCSprite* background=CCSprite::create("Helloworld.png"); background->setPosition(ccp(visibleSize.width/2,visibleSize.height/2)); this->addChild(background,0);//添加到场景,将其置于底部,z-index为0。 //创建一个纯文字按钮 CCLabelTTF *label1=CCLabelTTF::create("=Pause=","Arial",24);//先创建一个文字(标签文本label) CCMenuItemLabel *menu_item_label1=CCMenuItemLabel::create(label1,this,menu_selector(HelloWorld::pause)); //创建一个文字菜单项,其中第1个参数是显示的文字,最后一个参数是声明按钮的回调(执行)函数。 //如果,要创建一个纯图片的按钮,则同样先创建一个图片菜单项,用CCMenuItemImage *pCloseItem=CCMenuItemImage::create("CloseNormal.png","CloseSelected.png",menu_selector(Scene1::menuGoToHelloworld)); //这在官方自带的Helloworld就已经有, //在CCMenuItemImage中,第1个参数是正常状态的图片,第2个参数是被点击的图片,最后一个参数是声明按钮的回调(执行)函数。 CCMenu* menu1=CCMenu::create(menu_item_label1,NULL);//创建一个菜单,此菜单包含menu_item_label1这个菜单项,NULL是一定要有的。 menu1->setPosition(ccp(visibleSize.width/2,visibleSize.height/2));//菜单的位置,只能设置菜单的位置来定位,设置菜单项的位置是不使用的 //同时补充一句,Cocos2dx中菜单是没有中心点,因此menu1->setAnchorPoint(ccp(0,1));之类的不适用 this->addChild(menu1,1);//添加到场景,z-index为1。 //为上面的菜单创建一段连续、不间断、重复的动作序列 CCFiniteTimeAction* action1=CCMoveBy::create(3.0f,ccp(0,100));//在3秒内提升100px CCFiniteTimeAction* action2=CCMoveBy::create(3.0f,-100));//在3秒内下降100px CCFiniteTimeAction* repeat_action=CCRepeatForever::create(CCSequence::create(action1,action2,NULL));//这个动作无限重复 menu1->runAction(repeat_action);//菜单运行这个动作 return true; } void HelloWorld::pause(CCObject* pSender)//暂停按钮函数 { CCSize visibleSize=CCDirector::sharedDirector()->getVisibleSize();//获取当前层的尺寸 CCRenderTexture *renderTexture=CCRenderTexture::create(visibleSize.width,visibleSize.height);//通过CCRenderTexture保存当前界面(相当于截屏),然后传递给暂停界面,当成背景精灵 renderTexture->begin();//渲染开始 this->getParent()->visit();//遍历整个场景的组件,通通都会被保存到CCRenderTexture中 renderTexture->end();//渲染结束 CCDirector::sharedDirector()->pushScene(PauseScene::scene(renderTexture));//将游戏界面暂停,压入场景堆栈。并切换到GamePause界面 }
Helloworld这个场景弄完了,接下来完成PauseScene这个场景。
首先是PauseScene.h,对比与HelloWorldScene.h这个普通场景,PauseScene.h的scene()场景初始化函数是修改过的。
#include "cocos2d.h" //将此场景出栈的时候,自动找到栈最底部的Helloworld,因此无须声明#include "HelloWorldScene.h" USING_NS_CC;//一旦在头文件声明用到了CC,就必须有这句 class PauseScene:public cocos2d::CCLayer { public: virtual bool init(); static cocos2d::CCScene* scene(CCRenderTexture* renderTexture);//修改过的场景场景函数 CREATE_FUNC(PauseScene); private: void back(CCObject* pSender);//返回Helloworld场景的按钮事件 };
最后是PauseScene.cpp:
#include "PauseScene.h" CCScene* PauseScene::scene(CCRenderTexture* renderTexture)//收到在HelloWorldScene创建的纹理renderTexture { CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();//获取当前尺寸 CCScene *scene = CCScene::create();//创建场景 //根据纹理renderTexture创建此场景背景精灵background CCSprite* background=CCSprite::createWithTexture(renderTexture->getSprite()->getTexture()); background->setPosition(ccp(visibleSize.width/2,visibleSize.height/2));//此精灵居中 background->setFlipY(true);//垂直翻转此精灵 background->setColor(ccGRAY);//此精灵灰色显示,也就是蒙上一层灰色膜 scene->addChild(background); PauseScene *layer = PauseScene::create();//创建层 scene->addChild(layer); return scene; } bool PauseScene::init()//层的初始化 { CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();//获取当前尺寸 //创建一个纯文字按钮 CCLabelTTF* label1 =CCLabelTTF::create("=Back=",24); CCMenuItemLabel* menu_item_label1 = CCMenuItemLabel::create(label1,menu_selector(PauseScene::back)); CCMenu* menu1 = CCMenu::create(menu_item_label1,NULL); //menu1->setAnchorPoint(ccp(1,0));不适用于CCMenu,中心点默认在中央,因此只能利用加加减减摆好精灵的位置-_-! menu1->setPosition(ccp(visibleSize.width-menu_item_label1->getContentSize().width/2,0+menu_item_label1->getContentSize().height));//按钮的位置 this->addChild(menu1); return true; } void PauseScene::back(CCObject* pSender) { CCDirector::sharedDirector()->popScene();//本场景出栈 }
这里可能有人疑惑,为何创建的背景精灵涉及到垂直翻转的问题。
这是因为不垂直翻转不行,会变成如下的效果:
大概Cocos2dx在Helloworld这个场景遍历该场景的所有节点的时候,是从后开始遍历的。