cocos2d-x-3.0学习笔记之用户事件机制

原创 2016年08月28日 23:09:44

因为cocos2d-x引擎具有跨平台的特点,因此能够接收并处理的事件包括触摸事件,键盘事件,鼠标事件,加速度事件以及自定义事件等等。
现在的人机交互中,事件处理机制一般包括三个角色:事件、事件源和事件处理者。事件源是事件发生的场所(例如cocos里面的node),事件接收者是接收事件并处理事件的一段程序。
1.事件
cocos提供的事件类是Event,其子类主要包括触摸事件(EventTouch)、鼠标事件(EventMouse)、键盘事件(EventKeyboard)、加速度事件(EventAccleration)和自定义事件(EventCustom),其事件类图如下:
这里写图片描述

2.事件处理者
在cocos2d-x中的事件处理者是事件监听器类EventListener。子类主要包括单点触摸监听器(EventListenerTouchOneByOne), 多点触摸监听器(EventListenerTouchAllAtOnce), 键盘事件监听器(EventListenerKeyBoard), 鼠标事件监听器(EventListenerMouse), 加速度事件监听器(EventListenerAccleration), 自定义事件监听器(EventListenerCustom)。其类图如下所示:
这里写图片描述
3.由上面可以看出每一种事件都与其相对应的事件监听器绑定在一起,而这种绑定关系的过程被称为”注册监听器”。在cocos2d-x中,提供了一个事件分发器(EventDispatcher)来负责这种关系。也就是说事件监听器负责注册监听器、注销监听器、分发事件。
EventDispatcher类是一个单例类,Director::getInstance()->getEventDispatcher()可以得到事件分发器实例。EventDispatcher有两个注册监听器的函数,分别为:

void addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node);
//这个注册函数是将精灵显示的优先级作为作为事件的优先级

void addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority);
//制定固定的的时间优先级注册监听器,时间的优先级决定事件的响应优先级别,
//值越小,其优先级越高

EventListenerCustom* addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback);
//注册一个自定义事件,第一个参数时自定义事件的名称,
//第二个参数时响应事件的事件处理函数

4.在不需要进行事件响应时,需把先前注册的事件监听器给注销掉, cocos给我们提供了如下几个注销函数

void removeEventListener(EventListener* listener);
//注销指定的事件监听器

void removeEventListenersForType(EventListener::Type listenerType);
//根据事件类型注销所有的事件监听器

void removeEventListenersForTarget(Node* target, bool recursive = false);
//根据与事件绑定的节点来注销事件监听器

void removeCustomEventListeners(const std::string& customEventName);
//根据事件名注销自定义事件监听器

void removeAllEventListeners();
//注销所有事件监听器,使用该函数,所有触摸将不可用,包括菜单

二、事件运用
1.触摸事件
EventListenerTouchOneByOne处理函数

std::function<bool(Touch*, Event*)> onTouchBegan;
//当手指刚开始触摸时调用,返回true时调用后面的函数
std::function<void(Touch*, Event*)> onTouchMoved; 
//当手指在屏幕上移动时调用
std::function<void(Touch*, Event*)> onTouchEnded;
//当手指离开屏幕时调用
std::function<void(Touch*, Event*)> onTouchCancelled;
//当单点触摸事件被取消时调用

EventListenerTouchAllAtOnce(多点触控)

std::function<void(const std::vector<Touch*>&, Event*)>  onTouchesBegan;
std::function<void(const std::vector<Touch*>&, Event*)> onTouchesMoved;
std::function<void(const std::vector<Touch*>&, Event*)> onTouchesEnded;
std::function<void(const std::vector<Touch*>&, Event*)> onTouchesCancelled;

单点触摸实例:

Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();

    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Point origin = Director::getInstance()->getVisibleOrigin();
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }

    auto labe1 = LabelBMFont::create("HelloWorld", "fonts/Roboto.bmf.fnt");
    addChild(labe1, 1);
    labe1->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
    labe1->setOpacity(200); //设置透明度
    // add the label as a child to this layer

    //创建一个单点触控事件监听器
    auto listener = EventListenerTouchOneByOne::create();
    //如果事件被处理,则吞没该事件不继续分发

    listener->setSwallowTouches(true);
    listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::touchBegin, this);
    listener->onTouchMoved = CC_CALLBACK_2(HelloWorld::touchMoved, this);
    listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::touchEnded, this);

   //注册监听器
    EventDispatcher *eventDispatcher = Director::getInstance()->getEventDispatcher();
    eventDispatcher->addEventListenerWithSceneGraphPriority(listener, labe1);


    return true;
}

bool HelloWorld::touchBegin(Touch *touch, Event *event)
{
    log("touchbegin");
    return true;
}

void HelloWorld::touchMoved(Touch *touch, Event *event)
{
    log("touchmove");
}

void HelloWorld::touchEnded(Touch *touch, Event *event)
{
    log("touchend");
}

运行结果这里写图片描述

在cocos3.0之后,可以使用C++11标准的lambda表达式简化回掉代码

//创建一个单点触控事件监听器
    auto listener = EventListenerTouchOneByOne::create();
    //如果事件被处理,则吞没该事件不继续分发

    listener->setSwallowTouches(true);
    listener->onTouchBegan = [](Touch *touch, Event *event)
    {
        log("touchbegin");
        return true;
    };
    listener->onTouchMoved = [](Touch *touch, Event *event)
    {
        log("touchmove");
    };
    listener->onTouchEnded = [](Touch *touch, Event *event)
    {
        log("touchend");
    };

   //注册监听器
    EventDispatcher *eventDispatcher = Director::getInstance()->getEventDispatcher();
    eventDispatcher->addEventListenerWithSceneGraphPriority(listener, labe1);

2.键盘事件
使用方法与单点触控类似

std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed;  //按键按下调用
std::function<void(EventKeyboard::KeyCode, Event*)> onKeyReleased; //按键弹起调用

3.鼠标事件

std::function<void(Event* event)> onMouseDown; //鼠标按下
std::function<void(Event* event)> onMouseUp;  //鼠标抬起
std::function<void(Event* event)> onMouseMove; //鼠标移动
std::function<void(Event* event)> onMouseScroll;//鼠标滚轮滚动

三、在层中处理触摸
因为层是一个特殊的节点,因此除了上述方法响应事件外,cocos还单独为层重写了事件处理函数以方便调用

 virtual bool onTouchBegan(Touch *touch, Event *unused_event); 
    virtual void onTouchMoved(Touch *touch, Event *unused_event); 
    virtual void onTouchEnded(Touch *touch, Event *unused_event); 
    virtual void onTouchCancelled(Touch *touch, Event *unused_event);

    virtual void onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event);
    virtual void onTouchesMoved(const std::vector<Touch*>& touches, Event *unused_event);
    virtual void onTouchesEnded(const std::vector<Touch*>& touches, Event *unused_event);
    virtual void onTouchesCancelled(const std::vector<Touch*>&touches, Event *unused_event);

因为层中的事件处理是针对于整个Layer,因此如果想要得到具体点击的是Layer上的精灵,需要我们自己去判断,而不能指定具体精灵对象的优先级。

加速度事件
加速度时间的处理与前面类似,但是也有着细微的区别,一般处理工程如下:

//启用加速度硬件设备
    Device::setAccelerometerEnabled(true);
    //注册监听器
    EventDispatcher *eventDispatcher = Director::getInstance()->getEventDispatcher();
    auto listener = EventListenerAcceleration::create([](Acceleration *acc, Event *event){
        log("EventListenerAcceleration");
    });

这里 就了解了cocos常用事件的处理机制,能更灵活的运用它们。

相关文章推荐

Cocos2d-x中的数组类CCArray深入分析

前面的博文中我们提到了一个词典类CCDictionary,它和数组类CCArray共称Cocos2d-x两大常用数据结构,因为在项目中数组类CCArray我们使用的实在是太多了,因此这里补充一篇关于C...

非常量引用的初始值必须为左值的问题

原文地址:非常量引用的初始值必须为左值的问题作者:逆光Summer 首先,先看下面一个例子: eg.1 #includeiostream> usingnamespace std; ...

Cocos2d-x学习笔记(九)-------->Touch事件处理机制

Touch事件处理机制

cocos2d-x学习笔记——EventDispatcher事件分发机制

EventDispatcher 事件分发机制先创建事件,注册到事件管理中心 _eventDispatcher,通过发布事件得到响应进行回调,完成事件流。_eventDispatcher是Node的属性...

cocos2D-x 3.x学习笔记【二】 事件机制入门

cocos2Dx v3.x 有了不同于以往版本的事件机制,个人认为,相比起以往来说,这样的事件机制无疑更简洁和有效率,因为,我是从AS3转过来的,哈哈。 和AS3的事件机制有着很多相似。 ...

【Cocos2d-X开发学习笔记】第23期:事件处理机制之按键事件

本系列学习教程使用的是cocos2d-x-2.1.4(最新版为3.0alpha0-pre) ,PC开发环境Windows7,C++开发环境VS2010       一、按键事件         使用I...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:cocos2d-x-3.0学习笔记之用户事件机制
举报原因:
原因补充:

(最多只允许输入30个字)