cocos2dx3.1从零学习(二)菜单、场景切换、场景传值
转:http://www.it165.net/pro/html/201406/16195.html
回顾一下上一篇的内容,我们已经学会了创建一个新的场景scene,添加sprite和label到层中,掌握了定时事件schedule。我们可以顺利的写出打飞机的主场景框架。
上一篇的内容我练习了七个新场景,每一个场景都展示不同的东西,像背景定时切换、各种字体的随机颜色和位置等。每次要切换一个场景都要修改AppDelegate中的调用代码,非常的不方便查看,这一篇我们写场景的切换。每当我们创建一个新的场景的时候只要添加对应按钮到主界面,点击即可以切换过去查看对应的效果。这个有点类似官方提供的cpptest的查看方式,所以说场景切换是非常简单易用的功能。
要点击切换场景,必须要有按钮可以接收消息,所以首先学习一下菜单(Menu):
Menu创建菜单
MenuItem Create 菜单子项的创建
MenuItemFont是字菜子项。
1.
auto item= MenuItemFont::create(
"Hello,Menu"
,CC_CALLBACK_1(MenuScene::Menutest,
this
));
"Hello, Menu"是菜单子项按钮的文字。
MenuScene::Menutest是回调函数,它的参数是Menutest(Ref * pSender),这个参数类型是什么可以通过查看create定义来获得。
CC_CALLBACK_1就是绑定一个函数为回调函数,_1表示这个函数的只有一个参数。
我们的第一个菜单可以这样写:
01.
//开头这四句肯定是添加到init()函数里的
02.
auto item= MenuItemFont::create(
"Hello,Menu"
,CC_CALLBACK_1(MenuScene::Menutest,
this
));
03.
auto menu= Menu::create();
04.
menu->addchild(item);
05.
this
->addchild(menu);
06.
07.
voidMenuScene::Menutest(Ref *ref){
08.
//此处可以添加一个精灵,每点击一次菜单按钮就添加一个精灵到场景中。
09.
}
还可以这样创建一个菜单,不必每次都调用menu->addchild(item):
01.
auto item =MenuItemFont::create(
"Hello, Menu"
,CC_CALLBACK_1(MenuScene::Menutest,
this
));
02.
auto item1 =MenuItemFont::create(
"Ruck, Menu"
,CC_CALLBACK_1(MenuScene::Menutest1,
this
));
03.
auto item2 =MenuItemFont::create(
"Click, Menu"
,CC_CALLBACK_1(MenuScene::Menutest2,
this
));
04.
auto item3 =MenuItemFont::create(
"KTWork"
, CC_CALLBACK_1(MenuScene::KTWork,
this
));
05.
auto item4 =MenuItemFont::create(
"PushScene"
, CC_CALLBACK_1(MenuScene::PushScene,
this
));
06.
auto item5 =MenuItemFont::create(
"HomeWork"
, CC_CALLBACK_1(MenuScene::HomeWork,
this
));
07.
auto item6 =MenuItemFont::create(
"HomeWork0617"
,CC_CALLBACK_1(MenuScene::HomeWorkSnow,
this
));
08.
auto item7 =MenuItemFont::create(
"KT0618"
, CC_CALLBACK_1(MenuScene::KT0618,
this
));
09.
10.
auto menu =Menu::create(item, item1, item2, item3, item4, item5 ,item6,item7,<span style=
"color:#ff0000;"
>NULL);
//注意最后一个参数为空</span>
11.
menu->setPosition(Director::getInstance()->getVisibleSize().width/
2
,Director::getInstance()->getVisibleSize().height /
2
);
12.
menu->alignItemsVerticallyWithPadding(
40
);
//看英文就知道是垂直对齐 间隔40像素
13.
this
->addchild(menu);
在回调函数中操作菜单子项的属性:
voidMenuScene::Menutest1(Ref *ref){
MenuItemFont *item =(MenuItemFont *)ref;//所有的类的基类Ref,我们在菜单中是通过MenuItemFont创建的item,所以在回调函数中可以强制转换回MenuItemFont类型。然后就可以在回调函数中修改菜单子项的属性了。
01.
if
(item->getColor() == Color3B::RED)
02.
{
03.
item->setColor(Color3B::GREEN);
04.
item->setFontSizeObj(
55
);
05.
item->setFontNameObj(
"Baskerville-Boldltalic"
);
06.
item->setString(
"GreenClick"
);
07.
}
08.
else
09.
{
10.
item->setColor(Color3B::RED);
11.
item->setFontSizeObj(
24
);
12.
item->setFontName(
"Baskerville-Boldltalic"
);
13.
item->setString(
"RedClick"
);
14.
}
15.
}
从上面代码可以看到我创建了一个菜单里面有很多子项,这些子项都是场景切换。每一个新的场景都是一个练习。
见效果图:
关于创建菜单子项还有很多方法:
MenuItemLabel、MenuItemImage、MenuItemSprite等
下面拿MenuItemLabel举例(futura-48.fnt在我第一篇打飞机源码的素材里,源码在一楼,这种字体除了fnt还有一个png文件,是一起的,不能分开。这种字体创建的菜单就是下图中黄色的效果。)
autoitem2 =MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt","Start"), CC_CALLBACK_1(MenuSceneTwo::MenuTest, this));
具体的效果图看下面:
这是我的第一个Hello,Menu场景
上面已经介绍了菜单的创建,尝试这去创建一个新场景吧,点击按钮可以切换不同的背景。
给菜单子项绑定数据
在这里还要学习菜单子项item的两个操作函数。setUserData和setUserObject。
setUserData看定义接收的是void*参数,可以接收任意类型的数据。我们可以用它来传递C++的基本类型数据,但是千万不要自己new一些变量来传值,会造成意外的。
setUserObject接收的是继承自Ref的子类。继承自Ref的子类,最常用的就是cocos2dx本身的String了。
01.
auto item1 = MenuItemLabel::create(Label::createWithBMFont(
"fonts/futura-48.fnt"
,
"Easy"
), CC_CALLBACK_1(HomeWorkSnow::Start,
this
));
02.
item1->setUserObject(String::create(
"Easy"
));
03.
auto item2 = MenuItemLabel::create(Label::createWithBMFont(
"fonts/futura-48.fnt"
,
"Hard"
), CC_CALLBACK_1(HomeWorkSnow::Start,
this
));
04.
item2->setUserObject(String::create(
"Hard"
));
05.
auto item3 = MenuItemLabel::create(Label::createWithBMFont(
"fonts/futura-48.fnt"
,
"Difficult"
), CC_CALLBACK_1(HomeWorkSnow::Start,
this
));
06.
item3->setUserObject(String::create(
"Difficult"
));
07.
auto item4 = MenuItemLabel::create(Label::createWithBMFont(
"fonts/futura-48.fnt"
,
"Hell"
), CC_CALLBACK_1(HomeWorkSnow::Start,
this
));
08.
item4->setUserObject(String::create(
"Hell"
));
09.
auto menu = Menu::create(item1, item2, item3, item4, NULL);
10.
addChild(menu);
11.
menu->alignItemsVertically();
我们要把set的数据取出来,对应的两个函数是getUserData和getUserObject。
在菜单响应回调函数中,我们可以如下操作:
01.
void
HomeWorkSnow::Start(Ref *ref)
02.
{
03.
MenuItemLabel *item = (MenuItemLabel*)ref;
04.
String * str = (String *)item->getUserObject();
05.
06.
auto scene = HomeWorkSnowFight::createScene();
07.
HomeWorkSnowFight *layer = (HomeWorkSnowFight*)scene->getChildren().at(
0
);
08.
09.
layer->setData(mode[str->getCString()]);
10.
Director::getInstance()->pushScene(TransitionCrossFade::create(
1
, scene));
11.
12.
}
第一步是强转,我们用什么类型创建的item,在回调里我们就使用对应的类型强转回来。然后调用item的getUserObjet获取set的值。
后面三句是场景的正向传值,这个会在本篇最后讲到。提前提一下,就是调用下个场景层对象的成员函数做到传道的。
***********************************************************************************************************************************
切换场景
再创建一个新场景,然后使用下面语句添加到菜单回调函数来切换场景:
1.
auto scene =KTWork_SwitchBg::createScene();
2.
Director::getInstance()->replaceScene(scene);
这样我们就实现了从一个场景切换到另一个场景。
我们可以在另一个场景中尽情的添加想要的精灵,你也可以尝试把昨天创建的打飞机的场景添加进来,点击菜单按钮就可以开始打飞机了!
切换场景动画
如果要使用切换的特效动画,如下修改即可:
1.
auto scene =KTWork_SwitchBg::createScene();
2.
Director::getInstance()->replaceScene(TransitionPageTurn::create(
1
,scene,
true
));
还有(TransitionShrinkGrow::create(1,scene)); (TransitionCrossFade::create(1, scene));等
请多尝试几种特效方法Transition******::create()。
如果你想返回主菜单,只需要在子场景中添加一个返回的按钮即可,聪明的你肯定能想到怎么返回主菜单。
细心的话会发现切换场景的时候会提示有两个切换方式,一种是replacescene,一种是pushscene。这两种切换方式的区别在于,前者释放了当前场景,后者把当前场景压入栈中保存。pushscene的场景要切换回来,只需在子场景中调用popscene即可。 相当于原来的场景暂停了一会。
************************************************************************************************************
场景传值
正向传值
我们在切换场景之前,向下一个场景传递参数,这个是正向传值。
最简单的方法就是给下一个场景的类成员变量赋值。 这样我们就能在主场景控制我们在下一个场景想要展示的属性。
如下回调函数,我们返回的场景获取场景中所有的子节点。请右键查看getChildren的返回值。因为子场景中只有一个节点,所以我们第一个元素肯定是层,也就是 KTWork_PushScene类对象。然后我们可以使用tmp来任意正向传递参数给下个场景。
1.
voidMenuScene::PushScene(Ref *ref){
2.
this
->stopAllActions();
3.
auto scene =KTWork_PushScene::createScene();
4.
<span style=
"color:#ff0000;"
>KTWork_PushScene * tmp = (KTWork_PushScene*)(scene->getChildren().at(
0
));</span>
5.
Director::getInstance()->pushScene(TransitionShrinkGrow::create(
1
,scene));
6.
}
注意:我们在传递参数之前,KTWork_PushScene已经调用过init()函数初始化完毕,那我们应该怎么使传递的值生效呢?答案是使用虚函数onEnter()。onEnter是在切换场景后,展示场景前调用。所以我们可以如下修改代码:
1.
voidHomeWork::onEnter()
2.
{
3.
<span style=
"color:#ff0000;"
> Layer::onEnter();
//一定要先调用父类onEnter方法</span>
4.
label->setString(StringUtils::format(
"%s"
,strHp.getCString()));
//这样我们就动态修改了Label展示的值
5.
}
在类中我们通常设变量为私有,通过get、set方法来对其访问。在cocos2dx中,有一个宏可以替代我们定义这两个方法的操作。
1.
CC_SYNTHESIZE(
int
, hp, HP);
//定义了一个protected变量hp,定义了两个方法setHP,getHP来获取和设置hp的值。
2.
CC_SYNTHESIZE(String, strHp, sHP);
3.
CC_SYNTHESIZE_RETAIN(__String *, strname, Name);
//这个针对于指针变量。你现在使用可能会有崩溃的地方,这个在后面的内存管理会详细讲。这个宏定义没有想象的那么简单,提醒一下,要修改类的构造和析构函数。
这两个宏大家一定要自己去看一下是如何定义的。
总结:我们学习了菜单,触控响应,切换场景等,现在可以做一个 如下的游戏了。
有四种游戏模式,天空会降落雪花,每一种模式雪花大小不同。 鼠标点击可以使雪花小时。游戏结束返回主场景。
效果如下:
游戏代码我放到一楼去。 这些代码我后期也在优化。可能有一些知识点还没有涉及到。大家可以用一下素材。
可能会看到我主场景有飘雪花的特效,一些烟火特效。这些都是我复制别人的代码实现的,有兴趣的可以自己看一下,很简单。
cocos2dx3.1从零学习(二)菜单、场景切换、场景传值的更多相关文章
- Vue学习(二)-Vue中组件间传值常用的几种方式
版本说明:vue-cli:3.0 主要分为两类: 1.父子组件间的传值 2.非父子组件间的传值 1.父子组件间传值 父组件向子组件传值 第一种方式: props 父组件嵌套的子组件中,使用v-bind ...
- cocos2d-x实战 C++卷 学习笔记--第6章 场景与层
前言: 一个场景(Scene)是由多个层(Layer)组成,而且层的个数要至少是1,不能为0. 场景切换 场景切换相关函数 1)void runWithScene(Scene* scene) 该函 ...
- cocos2dx 3.1从零学习(四)——内存管理(错误案例分析)
本篇内容文字比較较多,可是这些都是建立在前面三章写代码特别是传值的时候崩溃的基础上的.可能表达的跟正确的机制有出入,还请指正. 假设有不理解的能够联系我.大家能够讨论一下,共同学习. 首先明白一个事实 ...
- 自制Unity小游戏TankHero-2D(5)声音+爆炸+场景切换+武器弹药
自制Unity小游戏TankHero-2D(5)声音+爆炸+场景切换+武器弹药 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm ...
- cocos2dx 3.1从零学习(二)——菜单、场景切换、场景传值
回想一下上一篇的内容,我们已经学会了创建一个新的场景scene,加入sprite和label到层中.掌握了定时事件schedule. 我们能够顺利的写出打飞机的主场景框架. 上一篇的内容我练习了七个新 ...
- 2、JavaScript 基础二 (从零学习JavaScript)
11.强制转换 强制转换主要指使用Number.String和Boolean三个构造函数,手动将各种类型的值,转换成数字.字符串或者布尔值. 1>Number强制转换 参数为原始类型值的转换规 ...
- es6从零学习(二):promise
es6从零学习(二):promise 一:promise的由来 某些情况下,回调嵌套很多时,代码就会非常繁琐,会给我们的编程带来很多的麻烦,这种情况俗称——回调地狱.由此,Promise的概念就由社区 ...
- 手牵手,从零学习Vue源码 系列二(变化侦测篇)
系列文章: 手牵手,从零学习Vue源码 系列一(前言-目录篇) 手牵手,从零学习Vue源码 系列二(变化侦测篇) 陆续更新中... 预计八月中旬更新完毕. 1 概述 Vue最大的特点之一就是数据驱动视 ...
- 场景切换特效Transition——Cocos2d-x学习历程(十二)
Transition 场景切换 在游戏中通常会用到一些场景的切换,比如从加载界面切换到欢迎界面.游戏中的所有场景存放在一个栈中,有且只有一个场景可以处于激活状态.直接replaceScene(即不适用 ...
随机推荐
- s:debug标签的错误ConcurrentModificationException
搭建SSH的时候页面上加入<s:debug>标签后台出现 严重: Servlet.service() for servlet jsp threw exception java.util.C ...
- [HTML] 使用size和maxlength分别控制文本框宽度和输入字符数的限制
① size一般可以直观的看到,就是文本框的宽度,只能决定文本框的宽度,也就是可以看到的字符的个数. 如:size="5" 这意味着如果输入 我的国家是北京 那么只能看见 我 ...
- Qt学习之路(tip): parent参数
这是一篇很简单的文章,仅仅是用来说明一下一个参数的作用,因此我把它写成了tip,而不是接下来的17. 程序写的多了,你会发现几乎所有的Qt类的构造函数都会有一个parent参数.这个参数通常是QO ...
- 象“[]”、“.”、“->”这类操作符前后不加空格
象“[]”.“.”.“->”这类操作符前后不加空格. #include <iostream> #include <process.h> #include<stdio ...
- 探讨:你真的会用Android的Dialog吗?
一个Bug前几日出现这样一个Bug是一个RuntimeException,详细信息是这样子的: 复制代码代码如下: java.lang.IllegalArgumentException: View n ...
- Ubuntu server版上使用命令行操作VPNclient
Ubuntu server版上使用命令行操作VPNclient VPN,虚拟专用网络,这个技术还是非常有用的.近期笔者參与的项目中就使用上了VPN,大概情况是这种.有两个开发团队,在异地,代码服务器在 ...
- pyqt二进制和图片的转换
参考:http://blog.chinaunix.net/uid-28194872-id-3516936.html MySQL数据库要想插入图片,其字段需要是BLOB类型.BLOB (binary l ...
- PHP删除目录及目录下所有文件或删除指定文件
PHP删除目录及目录下所有文件或删除指定文件 <?php header("content-type:text/html;charset=utf-8"); /** * 删除目录 ...
- mysqldump工具,通过--where选项,导出指定表中指定数据?
需求描述: 今天在使用mysqldump工具导出表的时候,考虑能不能导出满足条件的数据行,不要 将表都导出来,查找资料,通过--where选项,就可以实现目的,做个实验,在此记录下. 操作过程: 1. ...
- mysql数据库中,查看当前支持的字符集有哪些?字符集默认的collation的名字?
需求描述: mysql数据库支持很多字符集,那么如何查看当前的mysql版本中支持的或者说可用的字符集有什么呢? 操作过程: 1.使用show character set的方式获取当前版本中支持的字符 ...