最新文章
Cocos2d-x游戏开发实例详解7:对象释放时机
03-25 13:59
Cocos2d-x游戏开发实例详解6:自动释放池
03-25 13:55
Cocos2d-x游戏开发实例详解5:神奇的自动释放
03-25 13:49
Cocos2d-x游戏开发实例详解4:游戏主循环
03-25 13:44
Cocos2d-x游戏开发实例详解3:无限滚动地图
03-25 13:37
Cocos2d-x游戏开发实例详解2:开始菜单续
03-25 13:32
cocos2dx中多个场景之间如何传值
为了让大家清楚地了解在 Cocos2d-x 中多个场景之间如何传值,我们将从菜单的创建讲起,逐步展开整个操作流程。
1. 菜单创建基础
在创建新场景时,我们可以添加对应按钮到主界面,点击按钮即可切换场景查看效果,这与官方提供的 cpptest 的查看方式类似,场景切换是一个简单易用的功能。要实现点击切换场景,需要有按钮接收消息,因此我们先学习菜单(Menu)的相关内容。
1.1 菜单及菜单子项的创建
- MenuItemFont 创建菜单子项示例
auto item = MenuItemFont::create("Hello,Menu", CC_CALLBACK_1(MenuScene::Menutest, this)); "Hello, Menu"是菜单子项按钮显示的文字。MenuScene::Menutest是回调函数,其参数为Menutest(Ref * pSender),参数类型可通过查看create定义获取。CC_CALLBACK_1用于绑定一个函数为回调函数,_1表示该函数只有一个参数。创建第一个菜单的完整代码
// 开头这四句添加到 init() 函数里 auto item = MenuItemFont::create("Hello,Menu", CC_CALLBACK_1(MenuScene::Menutest, this)); auto menu = Menu::create(); menu->addChild(item); this->addChild(menu);
void MenuScene::Menutest(Ref *ref) { // 此处可以添加一个精灵,每点击一次菜单按钮就添加一个精灵到场景中。 }
<a id="heading-2-1-2-另一种菜单创建方式"></a>
### 1.2 另一种菜单创建方式
auto item = MenuItemFont::create("Hello, Menu", CC_CALLBACK_1(MenuScene::Menutest, this)); auto item1 = MenuItemFont::create("Ruck, Menu", CC_CALLBACK_1(MenuScene::Menutest1, this)); auto item2 = MenuItemFont::create("Click, Menu", CC_CALLBACK_1(MenuScene::Menutest2, this)); auto item3 = MenuItemFont::create("KTWork", CC_CALLBACK_1(MenuScene::KTWork, this)); auto item4 = MenuItemFont::create("PushScene", CC_CALLBACK_1(MenuScene::PushScene, this)); auto item5 = MenuItemFont::create("HomeWork", CC_CALLBACK_1(MenuScene::HomeWork, this)); auto item6 = MenuItemFont::create("HomeWork0617", CC_CALLBACK_1(MenuScene::HomeWorkSnow, this)); auto item7 = MenuItemFont::create("KT0618", CC_CALLBACK_1(MenuScene::KT0618, this));
auto menu = Menu::create(item, item1, item2, item3, item4, item5, item6, item7, NULL); // 注意最后一个参数为空 menu->setPosition(Director::getInstance()->getVisibleSize().width / 2, Director::getInstance()->getVisibleSize().height / 2); menu->alignItemsVerticallyWithPadding(40); // 垂直对齐,间隔 40 像素 this->addChild(menu);
<a id="heading-3-1-3-在回调函数中操作菜单子项的属性"></a>
### 1.3 在回调函数中操作菜单子项的属性
void MenuScene::Menutest1(Ref ref) { MenuItemFont item = (MenuItemFont *)ref; // 强制转换回 MenuItemFont 类型 if (item->getColor() == Color3B::RED) { item->setColor(Color3B::GREEN); item->setFontSizeObj(55); item->setFontNameObj("Baskerville-Boldltalic"); item->setString("GreenClick"); } else { item->setColor(Color3B::RED); item->setFontSizeObj(24); item->setFontName("Baskerville-Boldltalic"); item->setString("RedClick"); } }
<a id="heading-4-1-4-其他创建菜单子项的方法"></a>
### 1.4 其他创建菜单子项的方法
除了 `MenuItemFont`,还有 `MenuItemLabel`、`MenuItemImage`、`MenuItemSprite` 等方法。以下以 `MenuItemLabel` 为例:
// futura-48.fnt 在第一篇打飞机源码素材里,这种字体除了 fnt 还有一个 png 文件,需一起使用 auto item2 = MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt", "Start"), CC_CALLBACK_1(MenuSceneTwo::MenuTest, this));
<a id="heading-5-2--给菜单子项绑定数据"></a>
## 2. 给菜单子项绑定数据
菜单子项 `item` 有两个重要的操作函数:`setUserData` 和 `setUserObject`。
<a id="heading-6-2-1--setUserData-"></a>
### 2.1 `setUserData`
该函数接收 `void*` 类型的参数,可以接收任意类型的数据。但要注意,不要自己 `new` 一些变量来传值,以免造成意外。
<a id="heading-7-2-2--setUserObject-"></a>
### 2.2 `setUserObject`
此函数接收继承自 `Ref` 的子类,最常用的是 Cocos2d-x 本身的 `String` 类。示例代码如下:
auto item1 = MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt", "Easy"), CC_CALLBACK_1(HomeWorkSnow::Start, this)); item1->setUserObject(String::create("Easy")); auto item2 = MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt", "Hard"), CC_CALLBACK_1(HomeWorkSnow::Start, this)); item2->setUserObject(String::create("Hard")); auto item3 = MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt", "Difficult"), CC_CALLBACK_1(HomeWorkSnow::Start, this)); item3->setUserObject(String::create("Difficult")); auto item4 = MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt", "Hell"), CC_CALLBACK_1(HomeWorkSnow::Start, this)); item4->setUserObject(String::create("Hell"));
auto menu = Menu::create(item1, item2, item3, item4, NULL); addChild(menu); menu->alignItemsVertically();
<a id="heading-8-2-3-获取绑定的数据"></a>
### 2.3 获取绑定的数据
对应的获取数据的函数是 `getUserData` 和 `getUserObject`。在菜单响应回调函数中,操作如下:
void HomeWorkSnow::Start(Ref ref) { MenuItemLabel item = (MenuItemLabel)ref; String str = (String *)item->getUserObject();
auto scene = HomeWorkSnowFight::createScene(); HomeWorkSnowFight layer = (HomeWorkSnowFight)scene->getChildren().at(0);
layer->setData(mode[str->getCString()]); Director::getInstance()->pushScene(TransitionCrossFade::create(1, scene)); }
这里第一步是进行强转,使用什么类型创建的 `item`,在回调里就使用对应的类型强转回来,然后调用 `item` 的 `getUserObject` 获取设置的值。后面三句是场景的正向传值,后面会详细介绍。
<a id="heading-9-3--切换场景"></a>
## 3. 切换场景
<a id="heading-10-3-1-普通场景切换"></a>
### 3.1 普通场景切换
创建一个新场景,并在菜单回调函数中添加以下语句来切换场景:
auto scene = KTWork_SwitchBg::createScene(); Director::getInstance()->replaceScene(scene);
这样就实现了从一个场景切换到另一个场景。在新场景中,我们可以添加想要的精灵,也可以尝试添加之前创建的打飞机场景,点击菜单按钮即可开始游戏。
<a id="heading-11-3-2-切换场景动画"></a>
### 3.2 切换场景动画
如果要使用切换特效动画,修改代码如下:
auto scene = KTWork_SwitchBg::createScene(); Director::getInstance()->replaceScene(TransitionPageTurn::create(1, scene, true));
还有其他特效动画,如 `TransitionShrinkGrow::create(1, scene)`、`TransitionCrossFade::create(1, scene)` 等,可以多尝试不同的特效方法。
<a id="heading-12-3-3--replaceScene--和--pushScene--的区别"></a>
### 3.3 `replaceScene` 和 `pushScene` 的区别
在切换场景时,有 `replaceScene` 和 `pushScene` 两种方式。`replaceScene` 会释放当前场景,而 `pushScene` 会把当前场景压入栈中保存。如果使用 `pushScene` 切换场景,要切换回来,只需在子场景中调用 `popScene` 即可,相当于原来的场景暂停了一会。
<a id="heading-13-4--场景传值"></a>
## 4. 场景传值
<a id="heading-14-4-1-正向传值"></a>
### 4.1 正向传值
在切换场景之前,向下一个场景传递参数,即正向传值。最简单的方法是给下一个场景的类成员变量赋值,从而在主场景控制下一个场景想要展示的属性。示例代码如下:
void MenuScene::PushScene(Ref ref) { this->stopAllActions(); auto scene = KTWork_PushScene::createScene(); KTWork_PushScene tmp = (KTWork_PushScene*)(scene->getChildren().at(0)); Director::getInstance()->pushScene(TransitionShrinkGrow::create(1, scene)); }
<a id="heading-15-4-2-使传递的值生效"></a>
### 4.2 使传递的值生效
注意,在传递参数之前,`KTWork_PushScene` 已经调用过 `init()` 函数初始化完毕。为了使传递的值生效,我们可以使用虚函数 `onEnter()`。`onEnter` 是在切换场景后、展示场景前调用,示例代码如下:
void HomeWork::onEnter() { Layer::onEnter(); // 一定要先调用父类 onEnter 方法 label->setString(StringUtils::format("%s", strHp.getCString())); // 动态修改 Label 展示的值 }
<a id="heading-16-4-3-访问类成员变量的宏"></a>
### 4.3 访问类成员变量的宏
在类中,通常将变量设为私有,通过 `get`、`set` 方法来访问。在 Cocos2d-x 中,有一个宏可以替代我们定义这两个方法的操作。
通过以上步骤,我们详细介绍了在 Cocos2d-x 中创建菜单、切换场景以及场景之间传值的方法,希望能帮助大家更好地掌握相关技术。