[cocos2d-x 3.6]如何实现“侦听触摸事件和侦听按键事件”,触摸回调函数分别在什么情况下执行

来源:互联网 发布:安东尼奥尼 知乎 编辑:程序博客网 时间:2024/04/29 14:31

在以往的版本中,侦听触摸事件是这样写代码的:

class A : public CCLayer{    virtual bool init();    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);};

bool A::init(){    setTouchEnabled(true);}bool A::onTouchBegan(Touch *touch, Event *unused_event){    ....}void A::onTouchMoved(Touch *touch, Event *unused_event){    ....}void A::onTouchEnded(Touch *touch, Event *unused_event){    ....}void A::onTouchCancelled(Touch *touch, Event *unused_event){    ....}


在新版本中,上面这套做法被抛弃了。

在新版本中,有一个进化是,只要是Node的派生类都可以侦听触摸事件,也可以侦听按键事件,不再是只有CCLayer的派生类才能侦听。

在新版本中,侦听触摸事件要这样写:(回调函数不再是覆盖基类的虚函数)

class B : public Node{    virtual bool init();    bool myTouchBegan(Touch *touch, Event *unused_event);    void myTouchMoved(Touch *touch, Event *unused_event);    void myTouchEnded(Touch *touch, Event *unused_event);    void myTouchCancelled(Touch *touch, Event *unused_event);};
bool B::init(){    EventListenerTouchOneByOne* listener = EventListenerTouchOneByOne::create();    listener->setSwallowTouches(true);    listener->onTouchBegan = CC_CALLBACK_2(B::myTouchBegan, this);    listener->onTouchMoved = CC_CALLBACK_2(B::myTouchMoved, this);    listener->onTouchEnded = CC_CALLBACK_2(B::myTouchEnded, this);    listener->onTouchCancelled = CC_CALLBACK_2(B::myTouchCancelled, this);    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);}bool B::myTouchBegan(Touch *touch, Event *unused_event){    ....}void B::myTouchMoved(Touch *touch, Event *unused_event){    ....}void B::myTouchEnded(Touch *touch, Event *unused_event){    ....}void B::myTouchCancelled(Touch *touch, Event *unused_event){    ....}

相应的,侦听按键事件也不再是调用 setKeyboardEnabled() 函数了,新的写法是这样:

class C : public Node{    virtual bool init();    void myKeyPressed(EventKeyboard::KeyCode keyCode, Event* event);    void myKeyReleased(EventKeyboard::KeyCode keyCode, Event* event);};
bool C::init(){    EventListenerKeyboard* listener = EventListenerKeyboard::create();    listener->onKeyPressed = CC_CALLBACK_2(UILayerKeyListener::myKeyPressed, this);    listener->onKeyReleased = CC_CALLBACK_2(UILayerKeyListener::myKeyReleased, this);    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);}void C::myKeyPressed(EventKeyboard::KeyCode keyCode, Event* event){    ....}void C::myKeyReleased(EventKeyboard::KeyCode keyCode, Event* event){    ....}

可以看到,新版本中使用了一系列的EventListener的派生类

class CC_DLL EventListenerAcceleration : public EventListener
class CC_DLL EventListenerCustom : public EventListener
class CC_DLL EventListenerFocus : public EventListener
class CC_DLL EventListenerKeyboard : public EventListener
class CC_DLL EventListenerMouse : public EventListener
class CC_DLL EventListenerTouchOneByOne : public EventListener
class CC_DLL EventListenerTouchAllAtOnce : public EventListener

====================================================================================

触摸回调函数,在什么情况下会触发:
ccTouchBegan:触摸开始,返回true可以使得该触摸点属于该函数的目标对象,该点的变化只会影响该目标对象函数调用,不会影响其他对象。

ccTouchMoved:触摸点移动。

ccTouchEnded:触摸动作结束。

ccTouchCancelled:系统中断通知需要取消触摸事件的时候会调用此函数,这个中断往往是因为应用长时间没有响应或者当前视图从系统的顶层上移除了。

注意1,在ccTouchBegan返回时返回true,可以让这个触点属于这个函数的所属对象,并且其他对象不再接收该触点,这样之后再获得的触摸点肯定是它自己。这样就省去了你对多点触控时的判断。


注意2,有很多人认为手指移出屏幕或者目标对象的范围就会触发ccTouchCancelled,但是这种情况下调用的依然是ccTouchEnded函数。事实上,系统中断通知需要取消触摸事件的时候会调用ccTouchCancelled,这个中断被调用往往是因为出现如下几种情况:
  a、应用长时间没有响应或者当前视图从系统的顶层上移除。
  b、程序进入后台时,有可能是来点中断、电量低中断和部分机型上的Home键被按下。
  c、屏幕关闭和触摸的时候,某种原因导致距离传感器工作,比如:脸靠近。
  d、部分触摸权限覆盖了本应用的触摸权限。

注意3,触摸的优先级决定了触摸的分发顺序。触摸分发只和布景层的触摸优先级有关,和布景层的渲染顺序(zOrder)完全没有关系。哪怕是同样的触摸的优先级,也有可能底下一层先收到触摸,上面那层才接收到。所以处理不同层之间的触摸关系时,必须通过确定触摸优先级来实现这些层之间触摸点的处理顺序。优先级相同时数组里是乱序的,非插入顺序。


注意4,“吞噬”触摸点,如果在本布景层吞噬掉相应的触摸点,那么比它权限低的全都收不到触摸分发。







0 0
原创粉丝点击