cocos EventDispatcher事件分發機制

梁朝偉啊發表於2018-03-11

EventDispatcher 事件分發機制先建立事件,註冊到事件管理中心 _eventDispatcher,通過釋出事件得到響應進行回撥,完成事件流。_eventDispatcher是Node的屬性,通過它管理當前節點(場景、層、精靈等)的所有事件的分發。但它本身是一個單例模式值的引用,在Node的建構函式中,通過Director::getInstance()->getEventDispatcher(); 獲取,有了這個屬性,就能方便的處理事件。

有五種不同的事件機制:

  1. EventListenerTouch 響應觸控事件
  2. EventListenerKeyboard 響應鍵盤事件
  3. EventListenerAcceleration 響應加速器事件
  4. EventListenMouse 響應滑鼠事件
  5. EventListenerCustom 響應自定義的事件

優先順序:

  1. addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority) 中 fixedPriority 的值越低,則優先順序越高。
  2. 若優先順序相同。Layer 的z順序高的(繪製於頂部的)層將優於z順序低的層。這將保證了諸如觸碰事件的自頂向下傳播

  3. 注意:如果是固定優先值的監聽器新增到一個節點(addEventListenerWithFixedPriority),那當這個節點被移除時必須同時手動移除這個監聽器,但是新增場景圖優先監聽器到節點(addEventListenerWithSceneGraphPriority)就不用這麼麻煩,監聽器和節點是繫結好的,一旦節點的解構函式被呼叫,監聽器也會同時被移除。

觸控事件:

void EventDispatcherTest::funEventTouch(Sprite* sprite)
{
    this->_eventDispatcher->removeAllEventListeners();

    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = CC_CALLBACK_2(EventDispatcherTest::onTouchBeganss,this);
    listener->onTouchMoved = CC_CALLBACK_2(EventDispatcherTest::onTouchMovedss,this);
    listener->onTouchEnded = CC_CALLBACK_2(EventDispatcherTest::onTouchEndedss,this);
    listener->onTouchCancelled = CC_CALLBACK_2(EventDispatcherTest::onTouchCancelledss,this);

    listener->setSwallowTouches(true);//是否向下傳遞

    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,sprite);
}

bool EventDispatcherTest::onTouchBeganss(Touch* touch,Event* ev)
{
    auto target = static_cast<Sprite*>(ev->getCurrentTarget());

    Vec2 locationInNode = target->convertToNodeSpace(touch->getLocation());
    Size s = target->getContentSize();
    Rect rect = Rect(0, 0, s.width, s.height);
  //判斷觸控區域是否在目標上
    if (rect.containsPoint(locationInNode))
    {
        label->setString("onTouchBegan......");
        target->setOpacity(180);
        return true;
    }
    return false;
}
void EventDispatcherTest::onTouchMovedss(Touch* touch,Event* ev)
{
    auto target = static_cast<Sprite*>(ev->getCurrentTarget());
    target->setPosition(target->getPosition() + touch->getDelta());
    label->setString("onTouchMoved......");
}
void EventDispatcherTest::onTouchEndedss(Touch* touch,Event* ev)
{
    auto target = static_cast<Sprite*>(ev->getCurrentTarget());
    target->setOpacity(255);
    label->setString("onTouchEnded......");
}
void EventDispatcherTest::onTouchCancelledss(Touch* touch,Event* ev)
{
    label->setString("onTouchCancelled......");
}
  • 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

鍵盤事件:

void EventDispatcherTest::funEventKeyboard()
{
    this->_eventDispatcher->removeAllEventListeners();

    auto listener = EventListenerKeyboard::create();
    listener->onKeyPressed = CC_CALLBACK_2(EventDispatcherTest::onKeyPressedss,this);
    listener->onKeyReleased = CC_CALLBACK_2(EventDispatcherTest::onKeyReleasedss,this);
    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
}

void EventDispatcherTest::onKeyPressedss(EventKeyboard::KeyCode keycode,Event* ev)
{
    char txt[100] = {};
    sprintf_s(txt,"key %d is Pressed!",(int)keycode);
    label->setString(txt);
}

void EventDispatcherTest::onKeyReleasedss(EventKeyboard::KeyCode keycode,Event* ev)
{
    label->setString("key is Released!");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

滑鼠事件:

void EventDispatcherTest::funEventMouse(Sprite* sprite)
{
    this->_eventDispatcher->removeAllEventListeners();

    auto listener = EventListenerMouse::create();
    listener->onMouseDown = CC_CALLBACK_1(EventDispatcherTest::onMouseDownss,this);
    listener->onMouseMove = CC_CALLBACK_1(EventDispatcherTest::onMouseMovess,this);
    listener->onMouseUp = CC_CALLBACK_1(EventDispatcherTest::onMouseUpss,this);
    listener->onMouseScroll = CC_CALLBACK_1(EventDispatcherTest::onMouseScrollss,this);
    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,sprite);
}

void EventDispatcherTest::onMouseDownss(Event* ev)
{
    label->setString("onMouseDown!");
}
void EventDispatcherTest::onMouseMovess(Event* ev)
{
    label->setString("onMouseMove!");
}
void EventDispatcherTest::onMouseUpss(Event* ev)
{
    label->setString("onMouseUp!");
}
void EventDispatcherTest::onMouseScrollss(Event* ev)
{
    label->setString("onMouseScroll!");
}
  • 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

自定義事件:

//自定義事件
funEventCustom();
//2秒發派一次自定義事件,測試
scheduleOnce(schedule_selector(EventDispatcherTest::dispatcherCustomEvents),2.0f);

void EventDispatcherTest::funEventCustom()
{
    auto listener = EventListenerCustom::create("custom_event_1",CC_CALLBACK_1(EventDispatcherTest::onEventCustom,this));
    this->_eventDispatcher->addEventListenerWithFixedPriority(listener,1);//新增到事件分發器
}

void EventDispatcherTest::dispatcherCustomEvents(float at)
{
    //派發事件custom_event_1  事件內容為字串custom event test!
    this->_eventDispatcher->dispatchCustomEvent("custom_event_1","custom event test!");
}

void EventDispatcherTest::onEventCustom(EventCustom* event)
{
    auto data = static_cast<char*>(event->getUserData());
    label->setString(data);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

加速器事件:

 除了觸控,移動裝置上一個很重要的輸入源是裝置的方向,因此大多數裝置都配備了加速計,用於測量裝置靜止或勻速運動時所受到的重力方向。

重力感應來自移動裝置的加速計,通常支援X,Y和Z三個方向的加速度感應,所以又稱為三向加速計。在實際應用中,可以根據3個方向的力度大小來計算手機傾斜的角度或方向。

加速計監聽器EventListenerAcceleration,其靜態create方法中有個Acceleration的引數。Acceleration是一個類,包含了加速計獲得的3個方向的加速度。

void EventDispatcherTest::funEventAcceleration()
{
    //啟動硬體裝置
    Device::setAccelerometerEnabled(true); 

    auto listener = EventListenerAcceleration::create(CC_CALLBACK_2(EventDispatcherTest::onAcceleration,this));
    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
}

void EventDispatcherTest::onAcceleration(Acceleration* acc,Event* event)
{
    char str[100]={};
    sprintf_s(str,"x:%2d,y:%2d,z:%2d,timestamp:%2d",acc->x,acc->y,acc->z,acc->timestamp);
    log(str);
}

相關文章