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-x3.0和物理引擎实现碰撞检测

前言 从SpriteBatchNode中添加我们的精灵 首先,创建一个空白的项目,将实例代码删除。 接下来,让我们把资源文件放入的Resources目录下。 然后,在H...
  • llkk890320
  • llkk890320
  • 2014年05月15日 14:00
  • 4316

COCOS-3.X事件分发机制-触摸事件

在cocos中,触摸事件分为单点触摸和多点触摸,其中多点触摸主要是针对移动设备的,但是利用cocos的事件分发机制来处理触摸事件,其大致流程几乎是一致的。 一、单点触摸 1、cocos2.x的处理方式...
  • u011787119
  • u011787119
  • 2015年12月06日 23:38
  • 812

QT开发(十二)——QT事件处理机制

QT开发(十二)——QT事件处理机制一、QT事件简介    QT程序是事件驱动的, 程序的每个动作都是由内部某个事件所触发。QT事件的发生和处理成为程序运行的主线,存在于程序整个生命周期。    常见...
  • A642960662
  • A642960662
  • 2017年03月26日 12:46
  • 571

Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

其实我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客开始,就零零散散在好多地方使用到了Android事件分发的知识。也有好多朋友问过我各种问题,比如:onTouch和onTouc...
  • sinyu890807
  • sinyu890807
  • 2013年06月20日 08:30
  • 320118

Cocos2d-x学习笔记—事件处理机制

Cocos2d-x学习笔记—事件处理机制一:事件处理机制一个事件由触发到完成响应,主要由以下三部分组成: 事件分发器EventDispatcher; 事件类型EventTouch、EventKeybo...
  • hkchenhao
  • hkchenhao
  • 2016年07月10日 13:50
  • 2643

浅议Qt的事件处理机制 一

深入了解事件处理系统对于每个学习Qt人来说非常重要,可以说,Qt是以事件驱动的UI工具集。大家熟知Signals/Slots在多线程的实现也依赖于Qt的事件处理机制。     在Qt中,事件被封装成一...
  • abluemooon
  • abluemooon
  • 2016年01月08日 11:06
  • 680

Qt信号槽机制与事件机制的联系

http://blog.csdn.net/tingsking18/article/details/5157811 版权声明 本文为原创作品,请尊重作者的劳动成果。转载必须保持文章完整性,并...
  • zb872676223
  • zb872676223
  • 2014年04月15日 09:35
  • 1794

Android事件分发机制详解:史上最全面、最易懂

前言 Android事件分发机制是每个Android开发者必须了解的基础知识 网上有大量关于Android事件分发机制的文章,但存在一些问题:内容不全、思路不清晰、无源码分析、简单问题复杂化等等 今天...
  • carson_ho
  • carson_ho
  • 2017年01月06日 11:43
  • 36385

Nginx 事件机制介绍

先看几个主要方法 ngx_add_channel_event 主要是把事件注册到事件池中,并且添加事件 handler,具体要结合后面的事件机制来展开。 ngx_write_chann...
  • wangmanjie
  • wangmanjie
  • 2016年10月12日 08:15
  • 437

浅尝安卓事件分发机制

本文简单介绍安卓应用层的事件分发机制,并辅以案例进行分析。
  • zhaizu
  • zhaizu
  • 2016年01月25日 09:50
  • 2942
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:cocos2d-x-3.0学习笔记之用户事件机制
举报原因:
原因补充:

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