作者:慧科集团华东校区-朱家聪老师,转载请注明出处及本链接。
场景和层
在一个游戏中往往有多个场景和多个层。每个场景都有一个或者一个以上的层。在我们所创建的游戏工程中,AppDelegate.cpp文件中使用如下代码来创建一个新的场景:
// create a scene. it's an autorelease object
auto scene = HelloWorld::createScene();
// run
director->runWithScene(scene);
class HelloWorld : public cocos2d::Scene
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
virtual void onExit();
};
Scene* HelloWorld::createScene()
{
return HelloWorld::create();
}
在老版本的Cocos2d-x中,将HelloWorld定义为一个Layer。然后在createScene()
函数中创建所对应的Scene。再将HelloWorld层添加到这个场景中去。而在最新版本的Cocos2d-x中将HelloWorld直接定义为了一个Scene。在这个场景中我们可以去添加自己的层,来搭建我们需要的游戏场景或者UI界面。
场景过渡
一个完整的游戏一般是由多个场景构成的,这些场景之间需要做互相的切换和调度。以一个游戏的开始界面和设置界面为例来学习场景过渡的用法。
搭建开始游戏界面
//创建背景
Sprite *background = Sprite::create("background.png");
background->setContentSize(visibleSize);
background->setAnchorPoint(Vec2::ZERO);
background->setPosition(origin);
this->addChild(background);
//开始按钮
Sprite *startSpriteNormal = Sprite::create("start-up.png");
Sprite *startSpriteSelect = Sprite::create("start-down.png");
MenuItemSprite *startItem = MenuItemSprite::create(startSpriteNormal, startSpriteSelect, CC_CALLBACK_1(StartGameScene::startGame, this));
startItem->setPosition(Vec2(origin.x+visibleSize.width/2 - 100,origin.y+100));
//设置按钮
MenuItemImage *settingItem = MenuItemImage::create("setting-up.png", "setting-down.png", CC_CALLBACK_1(StartGameScene::settingCallback, this));
settingItem->setPosition(Vec2(origin.x+visibleSize.width/2 + 100, origin.y+100));
//菜单
Menu *menu = Menu::create(startItem, settingItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu);
场景的过渡和切换
在设置按钮的点击回调方法中,添加代码来完成场景的过渡。这里需要使用到的类是TransitionScene以及他的子类。TransitionScene是一个抽象类,表示用于做场景过渡效果的特殊场景,不能用来直接做场景的切换。而是应该用他的各种子类来实现场景切换的效果。这里我们使用TransitionMoveInL来完成一个从屏幕左边移动进入的场景切换效果。使用Director的pushScene函数来弹出一个新的场景。
void StartGameScene::settingCallback(Ref* pSender){
//创建设置界面场景
SettingScene *set = SettingScene::create();
auto *ts = TransitionMoveInL::create(1.0f, set);
Director::getInstance()->pushScene(ts);
};
搭建设置界面
//背景
Sprite *background = Sprite::create("setting-back.png");
background->setPosition(origin);
background->setAnchorPoint(Vec2::ZERO);
background->setContentSize(visibleSize);
this->addChild(background);
//音效
MenuItemImage *soundOn = MenuItemImage::create("on.png","on.png");
MenuItemImage *soundOff = MenuItemImage::create("off.png","off.png");
MenuItemToggle *soundToggle = MenuItemToggle::createWithCallback(CC_CALLBACK_1(SettingScene::toggleCallback, this), soundOn, soundOff, NULL);
soundToggle->setPosition(Vec2(origin.x+visibleSize.width - 150, origin.y+visibleSize.height / 2 + 10));
//背景音乐
MenuItemImage *musicOn = MenuItemImage::create("on.png","on.png");
MenuItemImage *musicOff = MenuItemImage::create("off.png","off.png");
MenuItemToggle *musicToggle = MenuItemToggle::createWithCallback(CC_CALLBACK_1(SettingScene::toggleCallback, this), musicOn, musicOff, NULL);
musicToggle->setPosition(Vec2(origin.x+visibleSize.width - 150, origin.y+visibleSize.height / 2 - 40));
//OK
MenuItemImage *okItem = MenuItemImage::create("ok-up.png", "ok-down.png", CC_CALLBACK_1(SettingScene::okButtonCallback, this));
okItem->setPosition(Vec2(origin.x+visibleSize.width / 2, 50));
//Menu
Menu *menu = Menu::create(soundToggle, musicToggle, okItem, NULL);
menu->setPosition(origin);
this->addChild(menu);
运行效果:
返回原场景
在设置界面的ok键的回调函数中,编写代码返回前一界面。因为我们在第一次界面转换时使用的是Push方法。这是一种类似于栈的场景管理方法,切换到后一个场景时,前一个场景不会被销毁。所以在需要返回时直接使用Pop方法进行弹出即可。
void SettingScene::okButtonCallback(Ref *pSender){
Director::getInstance()->popScene();
}
场景的生命周期
在Cocos2d-x中,多个场景在转换显示的时候会经历场景的创建和销毁。有一系列的函数可以用于操作在整个场景的生命周期中的各种事件。
系统函数
//场景的生命周期
bool SettingScene::init()
{
cout<<"场景初始化"<
多场景过渡
两个场景切换时,关系到两个场景之间的生命周期,在Start场景中也可以编写相关函数来同时监控两个场景。
//场景的生命周期
bool StartGameScene::init()
{
cout<<"场景初始化"<<"StartScene"<
在考虑多场景切换时,我们需要从以下三种情况来尝试。
使用pushScene()跳转到设置界面
在使用push的从场景1跳转到场景2时,场景1虽然会退出,但是并不会被清除。执行后的控制台输出结果如下:
场景初始化SettingScene
退出场景动画开始StartScene
进入场景SettingScene
退出场景StartScene
进入场景动画完成SettingScene
我们可以发现,StartScene并没有被清除,而只是暂时的退出了。
使用replaceScene()跳转到设置界面
replaceScene来实现场景跳转的时候,会在整个场景过渡动画结束之后清除掉StartScene。所以使用replaceScene来跳转的场景无法再使用popScene来进行返回。
场景初始化SettingScene
退出场景动画开始StartScene
进入场景SettingScene
退出场景StartScene
进入场景动画完成SettingScene
场景清除StartScene
使用popScene()返回前一场景
在使用popScene退出一个场景时会完全清楚这个场景并且退出它。
退出场景动画开始SettingScene
退出场景SettingScene
场景清除SettingScene
进入场景StartScene
进入场景动画完成StartScene