cocos2dx 场景间正向反向传

来源:互联网 发布:单桂敏艾条淘宝店铺 编辑:程序博客网 时间:2024/06/05 08:28

转载自:http://www.cnblogs.com/C-Plus-Plus/p/4021699.html

http://demo.netfoucs.com/hanbingfengying/article/details/32936385


正向传值:

场景A传值到场景B景B

 

A.cpp

复制代码
void A::onClick(CCObject * pObject){    // -----------------1.场景切换----------------------    CCScene * scene = B::scene();    B * layer = (B*)(scene->getChildren()->objectAtIndex(0));    layer->value = "要传的值";    CCDirector::sharedDirector()->replaceScene(scene );}
复制代码

B.h

复制代码
class B: public cocos2d::CCLayer{public:    virtual bool init();    virtual void onEnter();    static CCScene * scene();    CCString value;    CREATE_FUNC(B);};
复制代码

B.cpp

void B::onEnter(){    CCLayer::onEnter();    CCLog(value.getCString());}
反向传值

回调函数的实现(Lambda表达式

学习本篇前请仔细学习一下C++11的特性std::functionlambda表达式。C++11还引入了很多boost库的优秀代码使我们在使用的时候不必再加boost::,比如将要使用的std::bind;

学习地址如下

C++11function使用

lua闭包,iosblock,C++lambda函数

 

简单的说一下function的使用统一的函数定义格式function<int(int,float)>就相当于一种数据类型只不过int是定义一个整形数function是定义一个函数

view plaincopy to clipboardprint?
  1. function<int(int,float)>func = [](int a ,float b){return a+b;};//定义一个函数,名为func,它的第一个形参是int,第二个形参是float,返回值是int类型。int ret = func(3, 1.2f);  

 

首先让我们来看一下CC_CALLBACK_的定义

view plaincopy to clipboardprint?
  1. // new callbacksbased on C++11#defineCC_CALLBACK_0(__selector__,__target__, ...)std::bind(&__selector__,__target__, ##__VA_ARGS__)#defineCC_CALLBACK_1(__selector__,__target__, ...)std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)#defineCC_CALLBACK_2(__selector__,__target__, ...)std::bind(&__selector__,__target__, std::placeholders::_1,std::placeholders::_2, ##__VA_ARGS__)#defineCC_CALLBACK_3(__selector__,__target__, ...)std::bind(&__selector__,__target__, std::placeholders::_1,std::placeholders::_2, std::placeholders::_3, ##__VA_ARGS__)  

其实它们只是封装了bind的用法可以看到有几个参数,bind后面就跟几个_*。

要使用bindfunction需要引入头文件#include <functional>,bind的参数类型需要引入命名空间using namespace std::placeholders;

 

view plaincopy to clipboardprint?
  1. #include"stdafx.h"#include<iostream>#include<string>#include<functional>using namespace std;using namespacestd::placeholders; struct Foo {    Foo(int num) : num_(num) {}    void print_add(int i) const { std::cout<< num_ + i << '\n'; }    int num_;};int _tmain(int argc,_TCHAR* argv[]){    const Foo foo(123);   function<void(int)> f_add_display =bind(&Foo::print_add, foo, _1);return0;}  

注意:bind要绑定一个类函数的时候第二个参数必须是类对象

 

所以我们在菜单子项绑定回调函数的时候可以不使用CC_CALLBACK_1

view plaincopy to clipboardprint?
  1. auto item =MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt",itemName->getCString()));       item->setCallback(CC_CALLBACK_1(KT0618::change, this));  
等价于

view plaincopy to clipboardprint?
  1. auto item =MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt",itemName->getCString()));       item->setCallback(std::bind(&KT0618::change, this,std::placeholders::_1));  

也等价于

view plaincopy to clipboardprint?
  1. auto item =MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt",itemName->getCString()));       item->setCallback([=](Ref *ref)->void{//lambd表达式……         });  

 

如何正确定义和声明回调函数

   当我们create一个精灵的时候往往记不住这种类型的精灵的回调函数有几个参数参数类型是什么这里很重要的方法就是阅读api我们追踪进去看create方法源码create方法中查看需要的回调函数返回值是什么类型形参是什么类型复制过来即可


    在练习过程中我们要尽量不使用CC_CALLBACK_*,而是自己书写bind函数或者lambda表达式


***************************************************************************************************************

反向传值

    一个简单的应用场景游戏主界面展示最高分切换到游戏场景完成游戏后要向主场景返回成绩判断是否刷新纪录如果是的话就更新主界面的最高分

    前面我们学习了正向传值使用子场景的成员函数可以向子场景传值所谓反向传值可以理解为子场景传值回主场景

 

    根据我们上面学习的function,我们应该把主场景的函数指针利用子场景的成员函数传递给子场景存储起来然后在子场景中可以调用它的成员变量来调用主场景的函数 这样我们切换场景的时候只能pushScene,子场景使用popScene。否则主场景的对象都不存在了还如何实现回调呢?!

    新手可能会想再在子场景中实例化一个主场景的类对象这么就可以传递值了然后使用replace切换场景而不需要这么麻烦的传递一个函数指针如果按这种做法主场景和子场景要相互引用头文件实例化对方违反了低耦合的原则

 

在子场景头文件中这么定义

 

view plaincopy to clipboardprint?
  1. Public:    std::function<void(int)> func;  

我们就可以在主场景切换到子场景的时候这样来注册回调函数:

view plaincopy to clipboardprint?
  1. auto scene =HomeWorkSnowFight::createScene();HomeWorkSnowFight*layer = (HomeWorkSnowFight*)scene->getChildren().at(0);layer->func = std::bind(&HomeWorkSnow::callback1,this,std::placeholders::_1 );//绑定回调函数到子场景Director::getInstance()->pushScene(TransitionCrossFade::create(1,scene));  

这样我们在子场景中调用func(99);就相当于调用的主场景的callback1(99)


三 touch事件

陀螺仪

view plaincopy to clipboardprint?
  1. Device::setAccelerometerEnabled(true);   // auto ac =EventListenerAcceleration::create(CC_CALLBACK_2(KT0618::accelerationc, this));    auto ac =EventListenerAcceleration::create([&](Acceleration* acc, Event* e){       sp->setPositionX(acc->x+sp->getPositionX());    });   _eventDispatcher->addEventListenerWithSceneGraphPriority(ac, this);  

书写函数的时候仔细查看api,create有几个参数

比如陀螺仪create函数的形参格式如下

const std::function<void(Acceleration*, Event*)>& callback

这就说明需要传入的参数应该是有两个参数的void类型的函数对象

陀螺仪的代码只能在真机上测试了


键盘事件

xcode下是无法模拟的只有在VS下才能测试。下面的这些代码都是要牢记于心的,动手实现一下就明白了!

view plaincopy to clipboardprint?
  1. auto keyboardLs =EventListenerKeyboard::create();    keyboardLs->onKeyPressed =[=](EventKeyboard::KeyCode code, Event*event){        if(code==EventKeyboard::KeyCode::KEY_A)        {            CCLOG("AAA");        }    };    keyboardLs->onKeyReleased =[](EventKeyboard::KeyCode code, Event*event){        CCLOG("BBB");    };   _eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardLs,this);  

鼠标事件  单点触控

view plaincopy to clipboardprint?
  1. auto listen =EventListenerTouchOneByOne::create();    listen->onTouchBegan =CC_CALLBACK_2(KT0618::onTouchBegan, this);    listen->onTouchMoved =CC_CALLBACK_2(KT0618::onTouchMoved, this);    listen->onTouchEnded =CC_CALLBACK_2(KT0618::onTouchEnded, this);     listen->setSwallowTouches(true);   Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listen,this);  

动手实现一下拖动一个物体到另一个物体上只需要拖动到目的的边缘松开鼠标物体会自动放到中心处

 

b

view plaincopy to clipboardprint?
  1. oolKT0618::onTouchBegan(Touch *t, Event*e){    Point p = t->getLocation();    Rect rect = spMove->getBoundingBox();    if (rect.containsPoint(p))    {        return true;    }    else    {        return false;    }    return true;}voidKT0618::onTouchMoved(Touch *t, Event*e){    Point p = t->getLocation();    Rect rect = spMove->getBoundingBox();    if (rect.containsPoint(p))    {        spMove->setPosition(p);    }} voidKT0618::onTouchEnded(Touch *t, Event*e){    Point p = t->getLocation();    Rect rect = spBase->getBoundingBox();     if (rect.containsPoint(p))    {       spMove->setPosition(spBase->getPosition());    }}  

 

多点触控

iosAppController.mm加一句[eaglView setMultipleTouchEnabled:YES];在模拟器按住alt可以调试多点

windows就不用想了,surface除外

view plaincopy to clipboardprint?
  1. auto touchMore =EventListenerTouchAllAtOnce::create();    touchMore->onTouchesBegan =CC_CALLBACK_2(KT0618::onTouchesBegan, this);    touchMore->onTouchesMoved =CC_CALLBACK_2(KT0618::onTouchesMoved, this);    touchMore->onTouchesEnded =CC_CALLBACK_2(KT0618::onTouchesEnded, this);   _eventDispatcher->addEventListenerWithSceneGraphPriority(touchMore,this);  

onTouchesBegan跟单点触控返回值不同,请具体的根据api来写

view plaincopy to clipboardprint?
  1. void  KT0618::onTouchesBegan(conststd::vector<Touch*>& touches, Event* events){    for (auto v : touches )    {        v->getLocation();    }}voidKT0618::onTouchesMoved(const std::vector<Touch*>& touches, Event*unused_event){}void  KT0618::onTouchesEnded(conststd::vector<Touch*>& touches, Event *unused_event){}  

添加自定义消息响应EventListenerCustom

init()里面添加如下代码,那么这个层就会响应标志位shutdown的消息。

view plaincopy to clipboardprint?
  1. auto listenCustom =EventListenerCustom::create("shutdown",CC_CALLBACK_1(KT0618::popupLayerCustom, this));   Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(listenCustom,1);  

 

这样可以在需要发送shutdown消息的地方这样添加,第二个参数是这条消息的自定义参数。 

   _eventDispatcher->dispatchCustomEvent("shutdown", (void*)"Go!DongGuan!");
 

这样就往外分发了一个名字是shutdown的消息

这个消息可以在不同的层中接收到利用第二个参数可以做到数据传递可以是任何类型的数据比回调方便

其他层init也照上面添加并添加对应的响应函数

view plaincopy to clipboardprint?
  1. voidPopupLayer::shutdown(EventCustom * event){    char * str =(char *)event->getUserData();    CCLOG("Do not toucheme,bullshit!");    CCLOG(str);}  


添加音效

#include<SimpleAudioEngine.h>

usingnamespace CocosDenshion;

CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic(MUSIC_BG,true);

CocosDenshion:

:SimpleAudioEngine::sharedEngine()->playEffect(MUSIC_ENEMY1);

 

音效init的时候预加载,但是要注意切换场景的时候要释放掉预加载的音效。

view plaincopy to clipboardprint?
  1. CocosDenshion::SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(MUSIC_BG);CocosDenshion::SimpleAudioEngine::sharedEngine()->preloadEffect(MUSIC_BULLET);  
0 0
原创粉丝点击