• cocos2dx+lua注册事件函数详解 事件


    coocs2dx 版本 3.1.1

    registerScriptTouchHandler             注册触屏事件

    registerScriptTapHandler                  注册点击事件

    registerScriptHandler                         注册基本事件 包括 触屏 层的进入 退出 事件

    registerScriptKeypadHandler           注册键盘事件

    registerScriptAccelerateHandler      注册加速事件

    registerScriptTouchHandler 详解(可以设置单点或多点)

    function gameWindow:addLayerTouchEventMethod1()
        local function onTouchEvent(eventType, x, y)
            --log("eventType = "..tostring(eventType))
            if eventType == "began" then 
                --需要返回true
                return onTouchBegan(touch, event)
            elseif eventType == "moved" then 
                onTouchMoved(touch, event)
            elseif eventType == "ended" then 
                onTouchEnded(touch, event)
            end
        end
        config.bottomLayer:setTouchEnabled(true)
        config.bottomLayer:registerScriptTouchHandler(onTouchEvent)
    end


    registerScriptTapHandler                  注册点击事件 

    function gameWindow:addBtn()
        local btn = cc.MenuItemImage:create("white.png", "black.png", "black.png")
        btn:setPosition(320, 160)
        local function btnClick()
            log("btnClick")
        end
        btn:registerScriptTapHandler(btnClick)
    
        local menu = cc.Menu:create()
        config.bottomLayer:addChild(menu)
        menu:setPosition(cc.p(0,0))
    
        menu:addChild(btn)
    end


    registerScriptHandler                         注册基本事件 

    注册触屏事件用法

    function gameWindow:addLayerTouchEventMethod2()
        --创建一个单点触屏事件
        local listener = cc.EventListenerTouchOneByOne:create()
        --注册触屏开始事件
        listener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN)
        --注册触屏移动事件
        listener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED)
        --注册触屏结束事件
        listener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED)
        --获取层的事件派发器
        local eventDispatcher = config.bottomLayer:getEventDispatcher()
        --事件派发器 注册一个node事件
        eventDispatcher:addEventListenerWithSceneGraphPriority(listener, config.bottomLayer)
    end




    注册layer的 进入 退出事件用法

    function gameWindow:addLayerEnterAndExitEvent()
        local function onNodeEvent(eventType)
            if eventType == "enter" then
                log("enter")
            elseif eventType == "exit" then
                log("exit")
            end
        end
        config.bottomLayer:registerScriptHandler(onNodeEvent)
    end

     而在3.x中由于加入了C++11的特性,而对事件的分发机制通过事件分发器EventDispatcher 来进行统一的管理。

        事件监听器主要有:

        > 触摸事件     EventListenerTouchOneByOneEventListenerTouchAllAtOnce

        > 鼠标响应事件 EventListenerMouse

        > 键盘响应事件 EventListenerKeyboard

        > 加速计事件   EventListenerAcceleration

        > 自定义事件   EventListenerCustom

        > 物理碰撞事件 EventListenerPhysicsContact

        > 游戏手柄事件 EventListenerController

    【致谢】

        http://www.cnblogs.com/Richard-Core/p/3892641.html

        http://blog.csdn.net/runaying/article/details/16352879


    【事件分发器】

        事件分发器EventDispatcher,用于统一管理事件监听器的所有事件的分发。

    1、_eventDispatcher

        _eventDispatcher是Node的属性,通过Director::getInstance()->getEventDispatcher() 获得。

        _eventDispatcher的工作由三部分组成:

          (1)事件分发器 :EventDispatcher。

          (2)事件类型   :EventTouch, EventKeyboard 等。

          (3)事件监听器 :EventListenerTouch, EventListenerKeyboard 等。

        监听器实现了各种触发后的逻辑,在适当时候由事件分发器分发事件类型,然后调用相应类型的监听器。

    2、添加/删除监听器

        添加监听器:addEventListenerWithSceneGraphPriority 

                    addEventListenerWithFixedPriority 

        删除监听器:removeEventListener 

                    removeAllEventListeners 

    3、主要函数

        包含监听器的添加、删除、暂停、恢复,优先级的设置,手动分发事件等。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    //
    class EventDispatcher : public Ref
    {
    /**
     * 添加监听器
     *     - addEventListenerWithSceneGraphPriority
     *     - addEventListenerWithFixedPriority
     *     - addCustomEventListener
     */
        //使用 场景图的优先级 为指定事件添加一个监听. 
        //listener : 指定要监听的事件.
        //node     : 这个节点的绘制顺序是基于监听优先级. 
        //优先级   : 0
        void addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node);
     
        //使用 一定的优先级 为指定事件添加一个监听. 
        //listener      : 指定要监听的事件. 
        //fixedPriority : 这个监听器的固定优先级.
        //优先级        : fixedPriority。(但是不能为0,因为他是场景图的基本优先级)
        void addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority);
     
        //用户自定义监听器
        EventListenerCustom* addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback);
     
     
    /**
     * 删除监听器
     *     - removeEventListener
     *     - removeEventListenersForType
     *     - removeEventListenersForTarget
     *     - removeCustomEventListeners
     *     - removeAllEventListeners
     */
        //删除指定监听器
        void removeEventListener(EventListener* listener);
     
        //删除某类型对应的所有监听器
        //EventListener::Type::
        //  单点触摸 : TOUCH_ONE_BY_ONE
        //  多点触摸 : TOUCH_ALL_AT_ONCE
        //  键盘     : KEYBOARD
        //  鼠标     : MOUSE
        //  加速计   : ACCELERATION
        //  自定义   : CUSTOM
        void removeEventListenersForType(EventListener::Type listenerType);
     
        //删除绑定在节点target上的所有监听器
        void removeEventListenersForTarget(Node* target, bool recursive = false);
     
        //删除名字为customEventName的所有自定义监听器
        void removeCustomEventListeners(const std::string& customEventName);
     
        //移除所有监听器
        void removeAllEventListeners();
     
     
    /**
     * 暂停、恢复在节点target上的所有监听器
     *     - pauseEventListenersForTarget
     *     - resumeEventListenersForTarget
     */
        void pauseEventListenersForTarget(Node* target, bool recursive = false);
        void resumeEventListenersForTarget(Node* target, bool recursive = false);
     
     
    /**
     * 其他
     *     - setPriority
     *     - setEnabled
     *     - dispatchEvent
     *     - dispatchCustomEvent
     */
        //设置某监听器的优先级
        void setPriority(EventListener* listener, int fixedPriority);
     
        //启用事件分发器
        void setEnabled(bool isEnabled);
        bool isEnabled() const;
     
        //手动派发自定义事件
        void dispatchEvent(Event* event);
     
        //给名字为eventName的自定义监听器, 绑定用户数据
        void dispatchCustomEvent(const std::string &eventName, void *optionalUserData = nullptr);
    }
    //

    4、关于事件监听器的优先权

        通过 addEventListenerWithSceneGraphPriority 添加的监听器,优先权为0。

        通过 addEventListenerWithFixedPriority 添加的监听器,可以自定义优先权,但不能为0。

        优先级越低,越先响应事件。

        如果优先级相同,则上层的(z轴)先接收触摸事件。

    5、使用步骤

        (1)获取事件分发器  :dispatcher = Director::getInstance()->getEventDispatcher();

        (2)创建监听器      :auto listener = EventListenerTouchOneByOne::create();

        (3)绑定响应事件函数:listener->onTouchBegan = CC_CALLBACK_2(callback, this);

        (4)将监听器添加到事件分发器dispatcher中:

                dispatcher->addEventListenerWithSceneGraphPriority(Listener, this);

        (5)编写回调响应函数:

                bool callback(Touch* touch, Event* event) { ... }


    【触摸事件】

    1、单点触摸:EventListenerTouchOneByOne

        单点触摸监听器相关:

    1
    2
    3
    4
    5
    6
    7
    8
    //
        static EventListenerTouchOneByOne* create();
         
        std::function<bool(Touch*, Event*)> onTouchBegan; //只有这个返回值为 bool
        std::function<void(Touch*, Event*)> onTouchMoved;
        std::function<void(Touch*, Event*)> onTouchEnded;
        std::function<void(Touch*, Event*)> onTouchCancelled;
    //

        使用举例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    //
        //获取事件分发器
        auto dispatcher = Director::getInstance()->getEventDispatcher();
     
        //创建单点触摸监听器 EventListenerTouchOneByOne
        auto touchListener = EventListenerTouchOneByOne::create();
         
        //单点触摸响应事件绑定
        touchListener->onTouchBegan     = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
        touchListener->onTouchMoved     = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);
        touchListener->onTouchEnded     = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
        touchListener->onTouchCancelled = CC_CALLBACK_2(HelloWorld::onTouchCancelled, this);
         
        //在事件分发器中,添加触摸监听器,事件响应委托给 this 处理
        dispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
     
     
        //单点触摸事件响应函数
        bool onTouchBegan(Touch *touch, Event *unused_event)     { CCLOG("began"); return true; }
        void onTouchMoved(Touch *touch, Event *unused_event)     { CCLOG("moved"); }
        void onTouchEnded(Touch *touch, Event *unused_event)     { CCLOG("ended"); }
        void onTouchCancelled(Touch *touch, Event *unused_event) { CCLOG("cancelled"); }
    //

    2、多点触摸:EventListenerTouchAllAtOnce

        多点触摸监听器相关:

    1
    2
    3
    4
    5
    6
    7
    8
    //
        static EventListenerTouchAllAtOnce* create();
         
        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;
    //

        使用举例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    //
        //获取事件分发器
        auto dispatcher = Director::getInstance()->getEventDispatcher();
         
        //创建多点触摸监听器 EventListenerTouchAllAtOnce
        auto touchesListener = EventListenerTouchAllAtOnce::create();
         
        //多点触摸响应事件绑定
        touchesListener->onTouchesBegan     = CC_CALLBACK_2(HelloWorld::onTouchesBegan, this);
        touchesListener->onTouchesMoved     = CC_CALLBACK_2(HelloWorld::onTouchesMoved, this);
        touchesListener->onTouchesEnded     = CC_CALLBACK_2(HelloWorld::onTouchesEnded, this);
        touchesListener->onTouchesCancelled = CC_CALLBACK_2(HelloWorld::onTouchesCancelled, this);
         
        //在事件分发器中,添加触摸监听器,事件响应委托给 this 处理
        dispatcher->addEventListenerWithSceneGraphPriority(touchesListener, this);
     
     
        //多点触摸事件响应函数
        void onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event)    { CCLOG("began"); }
        void onTouchesMoved(const std::vector<Touch*>& touches, Event *unused_event)    { CCLOG("moved"); }
        void onTouchesEnded(const std::vector<Touch*>& touches, Event *unused_event)    { CCLOG("ended"); }
        void onTouchesCancelled(const std::vector<Touch*>&touches, Event *unused_event) { CCLOG("cancelled"); }
    //

    【鼠标事件】

        EventListenerMouse,主要用于监听鼠标的点击、松开、移动、滚轮的事件。

        鼠标事件监听器相关:

    1
    2
    3
    4
    5
    6
    7
    8
    //
        static EventListenerMouse* create();
     
        std::function<void(Event* event)> onMouseDown;     //按下鼠标, 单击鼠标
        std::function<void(Event* event)> onMouseUp;   //松开鼠标, 按下的状态下松开
        std::function<void(Event* event)> onMouseMove;  //移动鼠标, 在屏幕中移动
        std::function<void(Event* event)> onMouseScroll;//滚动鼠标, 滚动鼠标的滚轮
    //

        使用举例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    //
        //获取事件分发器
        auto dispatcher = Director::getInstance()->getEventDispatcher();
         
        //创建鼠标事件监听器 EventListenerMouse
        EventListenerMouse* mouseListenter = EventListenerMouse::create();
         
        //鼠标事件响应函数
        mouseListenter->onMouseDown   = CC_CALLBACK_1(HelloWorld::onMouseDown,   this);
        mouseListenter->onMouseUp     = CC_CALLBACK_1(HelloWorld::onMouseUp,     this);
        mouseListenter->onMouseMove   = CC_CALLBACK_1(HelloWorld::onMouseMove,   this);
        mouseListenter->onMouseScroll = CC_CALLBACK_1(HelloWorld::onMouseScroll, this);
         
        //添加鼠标事件监听器,事件响应处理委托给this
        dispatcher->addEventListenerWithSceneGraphPriority(mouseListenter, this);
         
         
        //事件响应函数
        void onMouseDown(Event* event)   { CCLOG("Down"); }
        void onMouseUp(Event* event)     { CCLOG("UP"); }
        void onMouseMove(Event* event)   { CCLOG("MOVE"); }
        void onMouseScroll(Event* event) { CCLOG("Scroll"); }
    //

    【键盘事件】

        EventListenerKeyboard,主要用于监听键盘某个键的按下、松开的事件。

        键盘事件监听器相关:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    //
        static EventListenerKeyboard* create();
     
        std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed;  //按下某键
        std::function<void(EventKeyboard::KeyCode, Event*)> onKeyReleased; //松开某键
     
         
        //键盘按键枚举类型 EventKeyboard::KeyCode
        //KeyCode的值对应的不是键盘的键值、也不是ASCII码,只是纯粹的枚举类型  
        //如:
        //  EventKeyboard::KeyCode::KEY_A
        //  EventKeyboard::KeyCode::KEY_1
        //  EventKeyboard::KeyCode::KEY_F1
        //  EventKeyboard::KeyCode::KEY_SPACE
        //  EventKeyboard::KeyCode::KEY_ALT
        //  EventKeyboard::KeyCode::KEY_SHIFT
    //

        使用举例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    //
        //获取事件分发器
        auto dispatcher = Director::getInstance()->getEventDispatcher();
     
        //创建键盘按键事件监听器
        EventListenerKeyboard* keyboardListener = EventListenerKeyboard::create();
         
        //绑定事件响应函数
        keyboardListener->onKeyPressed = CC_CALLBACK_2(HelloWorld::onKeyPressed, this);
        keyboardListener->onKeyReleased = CC_CALLBACK_2(HelloWorld::onKeyReleased, this);
         
        //添加监听器
        dispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, this);
         
         
        //事件响应函数
        void onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event) {
            if (EventKeyboard::KeyCode::KEY_J == keyCode) {
                CCLOG("Pressed: J");
            }
        }
        void onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event) {
            if (EventKeyboard::KeyCode::KEY_SPACE == keyCode) {
                CCLOG("Released: SPACE");
            }
        }
    //

    【加速计事件】

        EventListenerAcceleration,主要用于监听移动设备的所受重力方向感应事件。

        重力感应来自移动设备的加速计,通常支持 (X, Y, Z) 三个方向的加速度感应,所以又称为三向加速计。在实际应用中,可以根据3个方向的力度大小来计算手机倾斜的角度或方向。

    1、加速计信息类Acceleration

        该类中每个方向的加速度,大小都为一个重力加速度大小。

    1
    2
    3
    4
    5
    6
    //加速计信息
        class Acceleration
        {
            double x; double y; double z;
        };
    //

    2、开启加速计感应

        在使用加速计事件监听器之前,需要先启用此硬件设备:

            Device::setAccelerometerEnabled(true);

    3、加速计监听器相关

    1
    2
    3
    4
    5
    //
        static EventListenerAcceleration* create(const std::function<void(Acceleration*, Event*)>& callback);
     
        std::function<void(Acceleration*, Event*)> onAccelerationEvent;
    //

    4、使用举例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    //
        //标签: 显示加速计信息
        label = Label::createWithTTF("no used""Marker Felt.ttf", 12);
        label->setPosition(visibleSize / 2);
        this->addChild(label);
         
     
        //小球: 可视化加速计
        ball = Sprite::create("ball.png");
        ball->setPosition(visibleSize / 2);
        this->addChild(ball);
     
     
        //获取事件分发器
        auto dispatcher = Director::getInstance()->getEventDispatcher();
     
        //需要开启移动设备的加速计
        Device::setAccelerometerEnabled(true);
         
        //创建加速计事件监听器
        auto accelerationListener = EventListenerAcceleration::create(CC_CALLBACK_2(HelloWorld::onAccelerationEvent, this));
         
        //添加加速计监听器
        dispatcher->addEventListenerWithSceneGraphPriority(accelerationListener, this);
         
         
        //事件响应函数
        void HelloWorld::onAccelerationEvent(Acceleration* acceleration, Event* event)
        {
            char s[100];
            sprintf(s, "X: %f; Y: %f; Z:%f; ", acceleration->x, acceleration->y, acceleration->z);
            label->setString(s);
     
            //改变小球ball的位置
            float x = ball->getPositionX() + acceleration->x * 10;
            float y = ball->getPositionY() + acceleration->y * 10;
            Vec2 pos = Vec2(x, y);
            pos.clamp(ball->getContentSize() / 2, Vec2(288, 512) - ball->getContentSize() / 2);
            ball->setPosition(pos); //设置位置
        }
    //

    5、实际效果

        在电脑上看不出效果,需要移植到手机上,才能看到加速计的效果。

    wKioL1Qq6dCheq-6ABZS62wgGec329.gif


    【自定义事件】

        以上是系统自带的事件类型,事件由系统内部自动触发,如 触摸屏幕,键盘响应等。

        EventListenerCustom 自定义事件,它不是由系统自动触发,而是人为的干涉

        它的出现,使得2.x中的 观察者模式 NotificationCenter(订阅发布消息) 被无情的遗弃了。

        在 3.x 中,使用EventListenerCustom来实现消息的订阅与发布。

        学习它之前,最好了解一下 NotificationCenter 这个类的用法。

        NotificationCenter 的用法参见:http://shahdza.blog.51cto.com/2410787/1611575

    1、创建自定义监听器

        该监听器,就相当于是订阅消息。即与NotificationCenter的 addObserver 类似。

    1
    2
    3
    4
    5
    //
        //eventName : 监听器名字,即消息的名称
        //callback  : 监听器函数,即消息的回调函数
        static EventListenerCustom* create(const std::string& eventName, const std::function<void(EventCustom*)>& callback);
    //

    2、分发自定义事件

        自定义的事件监听器,需要通过手动的方式,将事件分发出去。

        > 通过 EventCustom(string eventName);       来设置需要发布消息的数据信息,eventName为消息名称。

            其中EventCustom可以通过setUserData来绑定想要传递的消息数据。

        > 通过 dispatcher->dispatchEvent(&event); 手动将事件分发出去。即发布消息。

            这与NotificationCenter的 postNotification 类似。

    1
    2
    3
    4
    5
    //
        EventCustom event("custom_event");
        event->setUserData((void*)123); // 绑定消息传递的数据,可以为任意类型void。
        dispatcher->dispatchEvent(&event); // 发布名称为"custom_event"的消息。
    //

    3、使用举例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    //
        //获取事件分发器
        auto dispatcher = Director::getInstance()->getEventDispatcher();
     
        //创建自定义事件监听器
        //监听器名字  : "custom_event"
        //事件响应函数: HelloWorld::onCustomEvent
        auto customListener = EventListenerCustom::create("custom_event", CC_CALLBACK_1(HelloWorld::onCustomEvent, this));
         
        //添加自定义事件监听器,优先权为1
        dispatcher->addEventListenerWithFixedPriority(customListener, 1);
     
         
        //手动分发监听器的事件,通过dispatchEvent发布名称为custom_event的消息。
        EventCustom event = EventCustom("custom_event");
        event->setUserData((void*)123); // 绑定消息传递的数据,可以为任意类型void。
        dispatcher->dispatchEvent(&event);
         
         
        //消息事件回调函数
        void HelloWorld::onCustomEvent(EventCustom* event)
        {
            // 获取消息传递的数据
            int* data = (int*)event->getUserData()
            CCLOG("onCustomEvent data = %d", data);
        }
    //

    4、说明

        > 每个自定义的事件监听器,都有一个监听器名字eventName。即为订阅的消息名称。

        > 需要通过 dispatcher->dispatchEvent(&event); 来手动将事件分发出去。即为发布消息。

        > 可以通过 dispatcher->dispatchCustomEvent(,); 来给自定义事件监听器绑定一个用户数据。


    【物理碰撞事件】

        有待研究。。。

    1
    2
    3
    4
    5
    6
    //
        EventListenerPhysicsContact;
        EventListenerPhysicsContactWithBodies;
        EventListenerPhysicsContactWithGroup;
        EventListenerPhysicsContactWithShapes;
    //

    【游戏手柄】

        有待研究。。。

    1
    2
    3
    //
        EventListenerController;
    //

     

  • 相关阅读:
    RMAN动态视图
    无归档模式下的备份
    验证备份集-使用DBVERIFY工具
    手工备份控制文件和参数文件
    针对发起alter tablespace test begin backup 断电情况的处理
    Jenkins一次任务构建中如何处理多个git仓库
    Element-ui Tree组件实现单选
    前端覆盖式发布引发的使用体验提升
    客户端localStorage命名冲突问题
    git 查看和删除分支
  • 原文地址:https://www.cnblogs.com/zhepama/p/4287220.html
Copyright © 2020-2023  润新知