回想一下上一篇的内容,我们已经学会了创建一个新的场景scene,加入sprite和label到层中。掌握了定时事件schedule。

我们能够顺利的写出打飞机的主场景框架。

上一篇的内容我练习了七个新场景。每个场景都展示不同的东西。像背景定时切换、各种字体的随机颜色和位置等。每次要切换一个场景都要改动AppDelegate中的调用代码。很的不方便查看,这一篇我们写场景的切换。每当我们创建一个新的场景的时候仅仅要加入相应button到主界面,点击即能够切换过去查看相应的效果。这个有点类似官方提供的cpptest的查看方式,所以说场景切换是很easy易用的功能。

要点击切换场景,必需要有button能够接收消息。所以首先学习一下菜单(Menu):

Menu创建菜单

MenuItem Create 菜单子项的创建

MenuItemFont是字菜子项。

  1. auto item= MenuItemFont::create("Hello,Menu",CC_CALLBACK_1(MenuScene::Menutest, this));

"Hello, Menu"是菜单子项button的文字。

MenuScene::Menutest是回调函数,它的參数是Menutest(Ref
* pSender),这个參数类型是什么能够通过查看create定义来获得。

CC_CALLBACK_1就是绑定一个函数为回调函数,_1表示这个函数的仅仅有一个參数。

我们的第一个菜单能够这样写:

  1. //开头这四句肯定是加入到init()函数里的
  2. auto item= MenuItemFont::create("Hello,Menu",CC_CALLBACK_1(MenuScene::Menutest, this));
  3. auto menu= Menu::create();
  4. menu->addchild(item);
  5. this->addchild(menu);
  6.  
  7. voidMenuScene::Menutest(Ref *ref){
  8. //此处能够加入一个精灵,每点击一次菜单button就加入一个精灵到场景中。
  9.  
  10. }

还能够这样创建一个菜单,不必每次都调用menu->addchild(item):

  1. auto item =MenuItemFont::create("Hello, Menu",CC_CALLBACK_1(MenuScene::Menutest,this));
  2. auto item1 =MenuItemFont::create("Ruck, Menu",CC_CALLBACK_1(MenuScene::Menutest1, this));
  3. auto item2 =MenuItemFont::create("Click, Menu",CC_CALLBACK_1(MenuScene::Menutest2, this));
  4. auto item3 =MenuItemFont::create("KTWork", CC_CALLBACK_1(MenuScene::KTWork,this));
  5. auto item4 =MenuItemFont::create("PushScene", CC_CALLBACK_1(MenuScene::PushScene,this));
  6. auto item5 =MenuItemFont::create("HomeWork", CC_CALLBACK_1(MenuScene::HomeWork,this));
  7. auto item6 =MenuItemFont::create("HomeWork0617",CC_CALLBACK_1(MenuScene::HomeWorkSnow, this));
  8. auto item7 =MenuItemFont::create("KT0618", CC_CALLBACK_1(MenuScene::KT0618,this));
  9.  
  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类型。然后就能够在回调函数中改动菜单子项的属性了。

  1. if (item->getColor() == Color3B::RED)
  2. {
  3. item->setColor(Color3B::GREEN);
  4. item->setFontSizeObj(55);
  5. item->setFontNameObj("Baskerville-Boldltalic");
  6. item->setString("GreenClick");
  7. }
  8. else
  9. {
  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场景

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFuYmluZ2Zlbmd5aW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

上面已经介绍了菜单的创建,尝试这去创建一个新场景吧,点击button能够切换不同的背景。

给菜单子项绑定数据

在这里还要学习菜单子项item的两个操作函数。setUserData和setUserObject。

setUserData看定义接收的是void*參数,能够接收随意类型的数据。我们能够用它来传递C++的基本类型数据,可是千万不要自己new一些变量来传值,会造成意外的。

setUserObject接收的是继承自Ref的子类。继承自Ref的子类,最经常使用的就是cocos2dx本身的String了。

  1. auto item1 = MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt", "Easy"), CC_CALLBACK_1(HomeWorkSnow::Start, this));
  2. item1->setUserObject(String::create("Easy"));
  3. auto item2 = MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt", "Hard"), CC_CALLBACK_1(HomeWorkSnow::Start, this));
  4. item2->setUserObject(String::create("Hard"));
  5. auto item3 = MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt", "Difficult"), CC_CALLBACK_1(HomeWorkSnow::Start, this));
  6. item3->setUserObject(String::create("Difficult"));
  7. auto item4 = MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt", "Hell"), CC_CALLBACK_1(HomeWorkSnow::Start, this));
  8. item4->setUserObject(String::create("Hell"));
  9. auto menu = Menu::create(item1, item2, item3, item4, NULL);
  10. addChild(menu);
  11. menu->alignItemsVertically();

我们要把set的数据取出来,相应的两个函数是getUserData和getUserObject。

在菜单响应回调函数中,我们能够例如以下操作:

  1. void HomeWorkSnow::Start(Ref *ref)
  2. {
  3. MenuItemLabel *item = (MenuItemLabel*)ref;
  4. String * str = (String *)item->getUserObject();
  5.  
  6. auto scene = HomeWorkSnowFight::createScene();
  7. HomeWorkSnowFight *layer = (HomeWorkSnowFight*)scene->getChildren().at(0);
  8.  
  9. 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);

这样我们就实现了从一个场景切换到还有一个场景。

我们能够在还有一个场景中尽情的加入想要的精灵。你也能够尝试把昨天创建的打飞机的场景加入进来。点击菜单button就能够開始打飞机了。

切换场景动画

假设要使用切换的特效动画,例如以下改动就可以:

  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()。

假设你想返回主菜单,仅仅须要在子场景中加入一个返回的button就可以,聪明的你肯定能想到怎么返回主菜单。

细心的话会发现切换场景的时候会提示有两个切换方式,一种是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);//这个针对于指针变量。你如今使用可能会有崩溃的地方,这个在后面的内存管理会具体讲。这个宏定义没有想象的那么简单,提醒一下,要改动类的构造和析构函数。

这两个宏大家一定要自己去看一下是怎样定义的。

通知NotificationCenter

  1. NotificationCenter::getInstance()->addObserver(this, callfuncO_selector(CocosStudio_SkeletonAnimate::onClick), "Ben", NULL);
  2. //收到事件之后要移除观察者以避免内存泄露
  3. NotificationCenter::getInstance()->postNotification("Ben", &CCString("Hello World"));

来看一下addObserver里面的源代码

  1. Ref* obj = nullptr;
  2. CCARRAY_FOREACH(_observers, obj)
  3. {
  4. NotificationObserver* observer = (NotificationObserver*) obj;
  5. if (!observer)
  6. continue;
  7.  
  8. if (observer->getName() == name && observer->getTarget() == target && observer->getSender() == sender)
  9. return true;
  10. }

加入通知的时候会对三个參数进行推断。也就是addObserver的第1、3、4个參数不能一样,否则仅仅会加入一次。

最后一个參数是Ref类型的,能够在回调函数中进行强转。能够对相应的Ref*进行处理,比方Label能够对其进行改动数值等。

最后切记:记得移除观察者(最好在onExit里)

总结:我们学习了菜单,触控响应,切换场景等,如今能够做一个 例如以下的游戏了。

有四种游戏模式。天空会降落雪花。每一种模式雪花大小不同。 鼠标点击能够使雪花小时。游戏结束返回主场景。

效果例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFuYmluZ2Zlbmd5aW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFuYmluZ2Zlbmd5aW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" style="font-size:11pt">

游戏代码我放到一楼去。 这些代码我后期也在优化。

可能有一些知识点还没有涉及到。

大家能够用一下素材。

可能会看到我主场景有飘雪花的特效,一些烟火特效。

这些都是我复制别人的代码实现的。有兴趣的能够自己看一下,非常easy。

cocos2dx 3.1从零学习(二)——菜单、场景切换、场景传值的更多相关文章

  1. cocos2dx 3.1从零学习(四)——内存管理(错误案例分析)

    本篇内容文字比較较多,可是这些都是建立在前面三章写代码特别是传值的时候崩溃的基础上的.可能表达的跟正确的机制有出入,还请指正. 假设有不理解的能够联系我.大家能够讨论一下,共同学习. 首先明白一个事实 ...

  2. cocos2dx 3.1从零学习(三)——Touch事件(回调,反向传值)

    第三讲 Touch 前面两篇我们学习的内容,足够我们做一款简单的小游戏.也能够说,我们已经入门了,能够蹒跚的走路了. 本篇将解说cocos2dx中非常重要的touch回调机制.你肯定记得第一章做定时器 ...

  3. Vue学习(二)-Vue中组件间传值常用的几种方式

    版本说明:vue-cli:3.0 主要分为两类: 1.父子组件间的传值 2.非父子组件间的传值 1.父子组件间传值 父组件向子组件传值 第一种方式: props 父组件嵌套的子组件中,使用v-bind ...

  4. cocos2dx 3.1从零学习(五)——动画

    动画是游戏中最重要的表现部分,本篇仅仅是初步学习大部分动画的用法.没有什么原理性的东西,可是样例有非常多,假设有不熟的地方要练一下. 特别是Spawn和Sequence的组合使用,什么时候使用Spaw ...

  5. cocos2dx 3.1从零学习(一)——入门篇(一天学会打飞机)

    没办法,浏览这么高,为啥没人投票呢?朋友们,我这篇文章參加了csdn博文大赛.喜欢的来点个赞吧!点击:http://vote.blog.csdn.net/Article/Details?article ...

  6. cocos2dx 3.1从零学习(六)——CocosStudio(VS2013project导入及环境设置)

    导入libCocosStudio.libExtensions.libGUI 新建的project例如以下图: 加入现有项目 右键解决方式.例如以下操作: watermark/2/text/aHR0cD ...

  7. cocos2d-x实战 C++卷 学习笔记--第6章 场景与层

    前言: 一个场景(Scene)是由多个层(Layer)组成,而且层的个数要至少是1,不能为0. 场景切换 场景切换相关函数 1)void  runWithScene(Scene*  scene) 该函 ...

  8. cocos2dx3.1从零学习(二)菜单、场景切换、场景传值

    转:http://www.it165.net/pro/html/201406/16195.html 回顾一下上一篇的内容,我们已经学会了创建一个新的场景scene,添加sprite和label到层中, ...

  9. 2、JavaScript 基础二 (从零学习JavaScript)

     11.强制转换 强制转换主要指使用Number.String和Boolean三个构造函数,手动将各种类型的值,转换成数字.字符串或者布尔值. 1>Number强制转换 参数为原始类型值的转换规 ...

随机推荐

  1. Coursera Algorithms Programming Assignment 2: Deque and Randomized Queue (100分)

    作业原文:http://coursera.cs.princeton.edu/algs4/assignments/queues.html 这次作业与第一周作业相比,稍微简单一些.有三个编程练习:双端队列 ...

  2. 使用Github做服务器展示前端页面

    1)在github上创建自己一个项目,项目名称必须是你的github账号名.github.io  譬如 fk123456.github.io 因为我已经创建了,所以显示名字重复. 2)使用命令行的方式 ...

  3. Cracking the Coding Interview 10.7

    Design an algorithm to find the kth number such that the only prime factors are 3,5 and 7 方法一: a[i]= ...

  4. NOI2007项链工厂——sbTreap代码

    #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> ...

  5. css选择器的综合使用

    代码实现: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf ...

  6. java中equals方法和==的用法

    java中equals方法的用法以及==的用法(参考一)equals 方法是 java.lang.Object 类的方法.两种用法说明:(1对于字符串变量来说,使用“==”和“equals()”方法比 ...

  7. 【sqli-labs】 less11 POST - Error Based - Single quotes- String (基于错误的POST单引号字符型注入)

    查看源码,用户名和密码通过post提交 加单引号提交 出现报错,推测对应的SQL语句 , 直接使用or构造永真登录 成功,注意此处登录的用户为表中的第一个用户 需要改变用户可以通过改变筛选条件实现 作 ...

  8. post请求获取json数据 解析json数据

    <script> window.onload = function () { var str; // console.log(@ViewBag.ID); $.post("/Ser ...

  9. 浏览器内置的base64方法

    Base64是一种基于64个可打印字符来表示二进制数据的表示方法.在Base64中的可打印字符包括字母A-Z.a-z.数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同(维基百科: ...

  10. 切换原生appium里面H5页面

    #coding = utf-8from appium import webdriverimport time'''1.手机类型2.版本3.手机的唯一标识 deviceName4.app 包名appPa ...