重新开始游戏、暂停游戏、关闭游戏是绝对是游戏的基础,虽然代码不多,不过这要利用到Cocos2dx导演类、场景类完成,事先如果不对其进行了解,绝对是很难做出来。
下面用一个小例子说明如何利用导演类、场景类完成重新开始游戏、暂停游戏、关闭游戏功能,
这个被改写的HelloWorld场景,一开始就声明一个在屏幕中央开始5s内上升100px的按钮精灵,
可以看到,点击左上角的Refresh!按钮,这个场景的所有动作会重新开始,也就是,将HelloWorld场景销毁,重新执行HelloWorld场景的init()函数,相当于“重新开始游戏”。
点击右上角的Pause!按钮会保存当前HelloWorld场景的所有操作,来到一个新的Pause场景,点击其中的Back!按钮,会重新返回HelloWorld场景,按钮精灵会继续执行在屏幕中央开始5s内上升100px的动作,而不是重新开始,相当于"暂停游戏"。
"关闭游戏"在官方的Helloworld已经有,不过涉及这里的相关的知识,也在这里说说。
工程的文件结构如下:
“暂停游戏”必须新建一个带“返回”按钮场景,不新建这个暂停场景,是做不出来,虽然新建场景是一件复杂的事情,但你不这样做,是搞不出来的。
关于场景的概念在《【Cocos2dx】新建场景、场景的切换、设置启动场景与菜单的新建》(点击打开链接)已经讲过了,但这里着重对场景的scene函数的重写,这个scene函数相当于场景新建时候执行的构造函数。
先看改写了的HelloWorldScene:
HelloWorldScene.h,一些声明,没什么好说,只是删除一些官方无用的预编译声明、注释:
#include "cocos2d.h"
#include "cocos-ext.h" //使用按钮事件,必须要需要的头文件
USING_NS_CC_EXT;//使用按钮事件,必须要需要的命名空间
class HelloWorld:public cocos2d::CCLayer
{
public:
virtual bool init();//场景初始化的函数
//场景声明函数
static cocos2d::CCScene* scene();
CREATE_FUNC(HelloWorld);
void pause(CCObject* pSender,CCControlEvent event);//暂停
void restart(CCObject* pSender,CCControlEvent event);//重新开始
void close(CCObject* pSender,CCControlEvent event);//关闭
};
HelloWorldScene.cpp,看起来代码很长很长,然而在init()声明N个按钮起始是一大堆重复的,详情可以看《【Cocos2dx】使用CCControlButton创建按钮、按钮点击事件,点击事件中的组件获取,setPosition的坐标问题 》( 点击打开链接),关键是各个函数的回调函数,核心是你要通过CCDirector::sharedDirector()召唤出导演,才能操作场景:
#include "HelloWorldScene.h"
#include "PauseScene.h"
USING_NS_CC;
CCScene* HelloWorld::scene()
{
CCScene *scene = CCScene::create();//创建HelloWorld场景
HelloWorld *layer = HelloWorld::create();//创建HelloWorld层
scene->addChild(layer);//将HelloWorld层放在HelloWorld场景,所有元素只能放在层上,而不能放在场景上,场景仅能放层,相当于JavaSwing中在frame中添加panel才能继续搞
return scene;
}
bool HelloWorld::init()
{
//获取屏幕的尺寸、位置信息等
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
//声明按钮部分
/*右上角按钮*/
CCScale9Sprite *btn_noraml1 = CCScale9Sprite::create("CloseNormal.png");//声明CloseNormal图片,用于按钮没被按下时的背景图片
CCLabelTTF *label1 = CCLabelTTF::create("Pause!","arial",36);//声明一个文字Pause!第2个参数是字体,仅能使用Resource文件夹中fonts文件夹中的字体,第3个参数是字体大小
CCControlButton *controlButton1 = CCControlButton::create(label1,btn_noraml1);
controlButton1->setAnchorPoint(ccp(1,1));
controlButton1->setPosition(ccp(visibleSize.width,visibleSize.height));
controlButton1->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::pause), CCControlEventTouchDown);//声明按钮的事件,第三个参数为定值常量意为,点击此按钮之后,触发第二个函数所声明的,下面给出的HelloWorld::pause(){}中所有代码。
this->addChild(controlButton1);//将此按钮添加到场景,默认不自动添加
/*左上角按钮*/
CCScale9Sprite *btn_noraml2 = CCScale9Sprite::create("CloseNormal.png");//声明CloseNormal图片,用于按钮没被按下时的背景图片
CCLabelTTF *label2 = CCLabelTTF::create("Refresh!","arial",36);//声明一个文字Refresh!第2个参数是字体,仅能使用Resource文件夹中fonts文件夹中的字体,第3个参数是字体大小
CCControlButton *controlButton2 = CCControlButton::create(label2,btn_noraml2);
controlButton2->setAnchorPoint(ccp(0,1));
controlButton2->setPosition(ccp(0,visibleSize.height));
controlButton2->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::restart), CCControlEventTouchDown);//声明按钮的事件,第三个参数为定值常量意为,点击此按钮之后,触发第二个函数所声明的,下面给出的HelloWorld::restart(){}中所有代码。
this->addChild(controlButton2);//将此按钮添加到场景,默认不自动添加
/*右下角按钮*/
CCScale9Sprite *btn_noraml3 = CCScale9Sprite::create("CloseNormal.png");//声明CloseNormal图片,用于按钮没被按下时的背景图片
CCLabelTTF *label3 = CCLabelTTF::create("Close!","arial",36);//声明一个文字Close!第2个参数是字体,仅能使用Resource文件夹中fonts文件夹中的字体,第3个参数是字体大小
CCControlButton *controlButton3 = CCControlButton::create(label3,btn_noraml3);
controlButton3->setAnchorPoint(ccp(1,0));
controlButton3->setPosition(ccp(visibleSize.width,0));
controlButton3->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::close), CCControlEventTouchDown);//声明按钮的事件,第三个参数为定值常量意为,点击此按钮之后,触发第二个函数所声明的,下面给出的HelloWorld::close(){}中所有代码。
this->addChild(controlButton3);//将此按钮添加到场景,默认不自动添加
/*声明一个做动作的按钮精灵,以显示出效果*/
CCSprite *sprite=CCSprite::create("CloseSelected.png");
sprite->setPosition(ccp(visibleSize.width/2,visibleSize.height/2));
this->addChild(sprite);
CCFiniteTimeAction* action2=CCMoveBy::create(5.0f,ccp(0,100));//在5秒内提升100px
sprite->runAction(action2);
return true;
}
void HelloWorld::pause(CCObject* pSender,CCControlEvent event)
{
//将游戏界面暂停,压入场景堆栈。并切换到GamePause界面
CCDirector::sharedDirector()->pushScene(PauseScene::scene());
}
void HelloWorld::restart(CCObject* pSender,CCControlEvent event)
{
//将游戏界面重新开始,replaceScene意思是用一个新场景替换旧场景,旧场景被替换之后,马上被销毁
CCDirector::sharedDirector()->replaceScene(HelloWorld::scene());
}
void HelloWorld::close(CCObject* pSender,CCControlEvent event)
{
//结束当前游戏
CCDirector::sharedDirector()->end();
exit(0);
}
PauseScene.h同样是一些声明:
#include "cocos2d.h"
#include "cocos-ext.h" //使用按钮事件,必须要需要的头文件
USING_NS_CC_EXT;//使用按钮事件,必须要需要的命名空间
using namespace cocos2d;
class PauseScene:public CCLayer{
public:
static CCScene* scene();
virtual bool init();
CREATE_FUNC(PauseScene);
void back(CCObject* pSender,CCControlEvent event);//返回场景
};
暂停功能是这样的:Cocos2dx自身就自带一个场景栈,在初始化的时候,在main.cpp指定的开始场景就会自动进入场景栈,具体见《【Cocos2dx】Windows平台下Cocos2dx 2.x的下载、安装、配置,打造自己的Helloworld》(点击打开链接),暂停的话,CCDirector::sharedDirector()召唤出来的导演,有令让某一场景进入场景栈的方法pushScene,Cocos2dx只会演出当前在场景栈最上方的场景,下方的所有场景的行为、元素位置,通通会被存档、暂停,待其回到场景栈最顶部才会继续运行。
导演同样有让当前在场景栈最上方的场景出栈的方法。场景被出栈是马上被销毁,再也找不到了。
如果场景栈为空,则会自动关闭游戏,不过建议还是用导演的end()与exit(0)方法来结束游戏,这也是Cocos2dx官方的Helloworld使用的方法。
#include "PauseScene.h"
USING_NS_CC;
CCScene* PauseScene::scene()
{
CCScene *scene=CCScene::create();
PauseScene* pauseScene=PauseScene::create();
scene->addChild(pauseScene);
return scene;
}
bool PauseScene::init()
{
//获取屏幕的尺寸、位置信息等
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
//声明按钮部分
cocos2d::extension::CCScale9Sprite *btn_noraml = cocos2d::extension::CCScale9Sprite::create("CloseNormal.png");//声明CloseNormal图片,用于按钮没被按下时的背景图片
CCLabelTTF *label1 = CCLabelTTF::create("back!","arial",36);//声明一个文字Click me!第2个参数是字体,仅能使用Resource文件夹中fonts文件夹中的字体,第3个参数是字体大小
CCControlButton *controlButton = CCControlButton::create(label1,btn_noraml);
controlButton->setPosition(ccp(visibleSize.width/2,visibleSize.height/2));//按钮的中心点位于屏幕的中央
controlButton->addTargetWithActionForControlEvents(this, cccontrol_selector(PauseScene::back), CCControlEventTouchDown);//声明按钮的事件,第三个参数为定值常量意为,点击此按钮之后,触发第二个函数所声明的,下面给出的PauseScene::back(){}中所有代码。
this->addChild(controlButton);//将此按钮添加到场景,默认不自动添加
return true;
}
void PauseScene::back(CCObject* pSender,CCControlEvent event)
{
//本场景出栈
CCDirector::sharedDirector()->popScene();
}