关闭

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

标签: cocos2d-x跨平台
102人阅读 评论(0) 收藏 举报
分类:

因为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常用事件的处理机制,能更灵活的运用它们。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:19841次
    • 积分:503
    • 等级:
    • 排名:千里之外
    • 原创:34篇
    • 转载:2篇
    • 译文:0篇
    • 评论:0条